Evolution of reproduction, survival, and body size in response to changing temperatures

Pottier et al.

latest update: 12 December 2024

Introduction

This Rmarkdown file summarises all code used to process, analyse, and visualise the data. However, note that the code for all statistical models requires extensive computational power, and ran on the computational cluster Katana supported by Research Technology Services at the University of New South Wales, Sydney (https://research.unsw.edu.au/katana). Please see the folder /R to find the files that were used to run the statistical models separately and the /pbs folder to find the resources needed to run each model. If you have any questions or find mistakes in the code presented below, please contact Patrice Pottier at

Load packages

pacman::p_load(tidyverse, purrr, ape, rotl, brms, orchaRd, metafor, emmeans, tidybayes,
    ggbeeswarm, kableExtra, ggtree, ggtreeExtra)
set.seed(234)

Data wrangling

Load raw data

# Load raw extracted data
raw_data <- read_csv("data_extraction/all_extracted_data.csv")
raw_data <- as.data.frame(raw_data)

# Rename body size values
raw_data$trait_type[raw_data$trait_type == "body size"] <- "body_size"
raw_data <- rename(raw_data, peer_reviewed = "peer-reviewed")

# Calculate the temperature difference between selection temperatures (in
# absolute values because it is modeled independently for warmer and colder
# lines)
raw_data <- raw_data %>%
    mutate(select_temp_diff = abs(treatment_temp - control_temp))

# Calculate the temperature difference between assay and control temperature
raw_data <- raw_data %>%
    mutate(assay_temp_diff = assay_temp - control_temp)

Convert confidence intervals to SE, and SE to SD

To use effective sample size properly, we need to first back-convert estimates reported as SE to SD.

processed_data <- raw_data %>%
    mutate(error_control = ifelse(error_type == "ci", error_control/1.96, error_control),
        error_treatment = ifelse(error_type == "ci", error_treatment/1.96, error_treatment)) %>%
    mutate(error_type = ifelse(error_type == "ci", "se", error_type))

processed_data <- raw_data %>%
    mutate(sd_control = ifelse(error_type == "se", error_control * sqrt(n_used_control),
        error_control), sd_treatment = ifelse(error_type == "se", error_treatment *
        sqrt(n_used_treatment), error_treatment))

processed_data <- processed_data %>%
    mutate(sd_control = ifelse(sd_control == 0, NA, sd_control), sd_treatment = ifelse(sd_treatment ==
        0, NA, sd_treatment))  # Replace values of 0 for the error by NA, as these result from a lack of sampling. 

Calculate effective sample sizes

Because the true level of replication in experimental evolution studies is the number of replicate selection lines, we calculated effective sample sizes to account for pseudo-replication. Effective sample sizes were calculated from formulas in Rutkowska et al. 2013. https://doi.org/10.1111/jeb.12282 ICC was taken as 0.5, which is conservative. It assumes that life history traits are repeatable between selection lines, so the effective sample size is closer to the number of lines than it is to the total number of individuals tested. When the number of animals was not available, the sample size was taken as the number of replicates.

# Calculate effective sample sizes
processed_data <- processed_data %>% 
  mutate(eff_n_control= ifelse(is.na(n_animals_control)==TRUE, 
                               n_control, 
                               n_animals_control / (1 + 0.5*((n_animals_control/n_control)-1))),
         
         eff_n_treatment= ifelse(is.na(n_animals_treatment)==TRUE, 
                               n_treatment, 
                               n_animals_treatment / (1 + 0.5*((n_animals_treatment/n_treatment)-1))))

Calculate effect sizes

Custom functions

Here, we use custom functions to calculate the average coefficient of variation and impute missing standard deviations. See Nakagawa et al. 2023 (Methods in Ecology and Evolution)

cv_avg <- function(x, sd, n, group, data, label = NULL, sub_b = TRUE, cv2 = FALSE) {

    # Check if the name is specified or not. If not, then assign it the name of
    # the mean, x, variable input in the function.
    # https://stackoverflow.com/questions/60644445/converting-tidyeval-arguments-to-string
    if (is.null(label)) {
        label <- purrr::map_chr(enquos(x), rlang::as_label)
    }

    # Calculate between study CV. Take weighted mean CV within study, and then
    # take a weighted mean across studies of the within study CV. Weighted
    # based on sample size and pooled sample size.
    b_grp_cv_data <- data %>%
        dplyr::group_by({
            {
                group
            }
        }) %>%
        dplyr::mutate(w_CV2 = weighted_CV({
            {
                sd
            }
        }, {
            {
                x
            }
        }, {
            {
                n
            }
        }, cv2 = cv2), n_mean = mean({
            {
                n
            }
        }, na.rm = TRUE)) %>%
        dplyr::ungroup(.) %>%
        dplyr::mutate(b_CV2 = weighted.mean(w_CV2, n_mean, na.rm = TRUE), .keep = "used")

    # Make sure that label of the calculated columns is distinct from any other
    # columns
    names(b_grp_cv_data) <- paste0(names(b_grp_cv_data), "_", label)

    # Append these calculated columns back to the original data and return the
    # full dataset.
    if (sub_b) {
        b_grp_cv_data <- b_grp_cv_data %>%
            dplyr::select(grep("b_", names(b_grp_cv_data)))
        dat_new <- cbind(data, b_grp_cv_data)
    } else {
        dat_new <- cbind(data, b_grp_cv_data)
    }

    return(data.frame(dat_new))
}

# Helper function
weighted_CV <- function(sd, x, n, cv2 = FALSE) {
    if (cv2) {
        weighted.mean(na_if((sd/x)^2, Inf), n, na.rm = TRUE)
    } else {
        weighted.mean(na_if((sd/x), Inf), n, na.rm = TRUE)^2
    }
}

Impute missing standard deviations and calculate effect sizes

Different formulas were used for independent and dependent samples (see methods).

# Calculate average standard deviations
processed_data <- cv_avg(x=mean_control, sd = sd_control, n=eff_n_control, group = ref, label = "control", data = processed_data) # Control
processed_data <- cv_avg(x=mean_treatment, sd = sd_treatment, n=eff_n_treatment, group = ref, label = "treatment", data = processed_data) # Treatment

# Multiply the coefficient of variation by the mean to get SD
processed_data <- processed_data %>% mutate(sd_control = ifelse(is.na(sd_control)==TRUE,
                                                                b_CV2_control*mean_control,
                                                                sd_control),
                                            sd_treatment = ifelse(is.na(sd_treatment)==TRUE,
                                                                b_CV2_treatment*mean_treatment,
                                                                sd_treatment))

# Add a column to identify observations sharing the same cohort IDs
processed_data <- processed_data %>%
  group_by(cohort_ID) %>%
  mutate(n_cohort = n()) %>%
  ungroup()

# Calculate effect sizes for independent and dependent (traits measured on the same animals) samples.
processed_data <- processed_data %>% mutate(
  # Log response ratio (lnRR)
  lnRR = log(mean_treatment/mean_control) + 
                (0.5 * ((sd_treatment^2/(eff_n_treatment*mean_treatment^2)) -    
                       (sd_control^2/(eff_n_control*mean_control^2)))), # Formula 4 in Senior et al. 2020
    
  # Sampling variance of lnRR
  var_lnRR = ifelse(n_cohort == 1, # If samples are independent
    
             (sd_control^2/(eff_n_control*mean_control^2)) + 
             (sd_control^4/(2*eff_n_control^2*mean_control^4)) + 
             (sd_treatment^2/(eff_n_treatment*mean_treatment^2)) +
             (sd_treatment^4/(2*eff_n_treatment^2*mean_treatment^4)), # Formula 14 in Senior et al. 2020
  
             (sd_control^2/(eff_n_control*mean_control^2)) +  # else use this formula if samples are dependent
             (sd_treatment^2/(eff_n_treatment*mean_treatment^2)) +
             (sd_control^4/(2*eff_n_control^2*mean_control^4)) + 
             (sd_treatment^4/(2*eff_n_treatment^2*mean_treatment^4)) - 
             (0.5 * ((2*sd_control*sd_treatment)/(eff_n_control*mean_control*mean_treatment))) + 
             (0.5^2 * ((sd_control^2*sd_treatment^2*(mean_control^4+mean_treatment^4))/(2*eff_n_control^2*mean_control^4*mean_treatment^4))) # Formula 19 in Senior et al. 2020
  ),
  
  # Log variance ratio (lnVR)
  lnVR = log(sd_treatment/sd_control) + 
                (0.5 * ((1/(eff_n_treatment-1)) -    
                       (1/(eff_n_control-1)))), # Formula 5 in Senior et al. 2020
  
  # Sampling variance of lnVR
  var_lnVR = ifelse(n_cohort ==1, # If samples are independent
    
    0.5 * ((eff_n_control/((eff_n_control-1)^2)) + (eff_n_treatment/((eff_n_treatment-1)^2))), # Formula 15 in Senior et al. 2020
    (eff_n_control/(eff_n_control - 1)^2) - (0.5^2*(1/(eff_n_control-1))) + (0.5^4*((sd_control^8+sd_treatment^8)/(2*((eff_n_control-1)^2)*sd_control^4*sd_treatment^4))) # Formula 22 in Senior et al. 2020
  ),       
  
  # Log coefficient of variation ratio (lnCVR)
  lnCVR = log((sd_treatment/mean_treatment)/(sd_control/mean_control)) + 
                (0.5 * ((1/(eff_n_treatment-1)) -    
                       (1/(eff_n_control-1)))) + 
                (0.5 * ((sd_control^2/(eff_n_control*mean_control^2)) -    
                       (sd_treatment^2/(eff_n_treatment*mean_treatment^2)))), # Formula 6 in Senior et al. 2020
  
  # Sampling variance of lnCVR
  var_lnCVR = ifelse(n_cohort==1, # If samples are independent
              
              (sd_control^2/(eff_n_control*mean_control^2)) + 
              (sd_control^4/(2*eff_n_control^2*mean_control^4)) + 
              (eff_n_control/((eff_n_control-1)^2)) + 
              (sd_treatment^2/(eff_n_treatment*mean_treatment^2)) + 
              (sd_treatment^4/(2*eff_n_treatment^2*mean_treatment^4)) + 
              (eff_n_treatment/((eff_n_treatment-1)^2)), # Formula 16 in Senior et al. 2020
   
              (sd_control^2/(eff_n_control*mean_control^2)) + 
              (sd_treatment^2/(eff_n_treatment*mean_treatment^2)) + 
              (sd_control^4/(2*eff_n_control^2*mean_control^4)) + 
              (sd_treatment^4/(2*eff_n_treatment^2*mean_treatment^4)) - 
              (0.5 * ((2*sd_control*sd_treatment)/(eff_n_control*mean_control*mean_treatment))) + 
              (0.5^2 * (sd_control^2*sd_treatment^2*(mean_control^4+mean_treatment^4))/(2*eff_n_control^2*mean_control^4*mean_treatment^4)) + 
              (eff_n_control/((eff_n_control-1)^2)) - 
              (0.5^2 * (1/(eff_n_control-1))) + 
              (0.5^4 * (sd_control^8+sd_treatment^8)/(2*((eff_n_control-1)^2)*sd_control^4*sd_treatment^4)) # Formula 24 in Senior et al. 2020
  ))

Save processed dataset

# Save processed data
write.csv(processed_data, file = "data/processed_data.csv")

Account for data non-independence

Phylogenetic variation

processed_data <- read_csv(file = "data/processed_data.csv")

data <- processed_data
unique(data$species)  # 25 species
##  [1] "Drosophila melanogaster"    "Sepsis punctum"            
##  [3] "Musca domestica"            "Poecilia reticulata"       
##  [5] "Daphnia pulicaria"          "Ophryotrocha labronica"    
##  [7] "Callosobruchus maculatus"   "Tribolium castaneum"       
##  [9] "Caenorhabditis remanei"     "Drosophila serrata"        
## [11] "Apocyclops royi"            "Rhizoglyphus robini"       
## [13] "Drosophila subobscura"      "Zabrotes subfasciatus"     
## [15] "Eurytemora affinis"         "Drosophila buzzatii"       
## [17] "Callosobruchus chinensis"   "Drosophila bipectinata"    
## [19] "Drosophila hydei"           "Drosophila pseudoananassae"
## [21] "Simocephalus vetulus"       "Daphnia magna"             
## [23] "Daphnia pulex"              "Brachionus plicatilis"     
## [25] "Danio rerio"
# Match species to the OTL database
taxa <- unique(data$species)
resolved_names <- tnrs_match_names(taxa, context_name = "Animals")
resolved_names  # All good, no approximate matches
##                 search_string                unique_name approximate_match
## 1     drosophila melanogaster    Drosophila melanogaster             FALSE
## 2              sepsis punctum             Sepsis punctum             FALSE
## 3             musca domestica            Musca domestica             FALSE
## 4         poecilia reticulata        Poecilia reticulata             FALSE
## 5           daphnia pulicaria          Daphnia pulicaria             FALSE
## 6      ophryotrocha labronica     Ophryotrocha labronica             FALSE
## 7    callosobruchus maculatus   Callosobruchus maculatus             FALSE
## 8         tribolium castaneum        Tribolium castaneum             FALSE
## 9      caenorhabditis remanei     Caenorhabditis remanei             FALSE
## 10         drosophila serrata         Drosophila serrata             FALSE
## 11            apocyclops royi            Apocyclops royi             FALSE
## 12        rhizoglyphus robini        Rhizoglyphus robini             FALSE
## 13      drosophila subobscura      Drosophila subobscura             FALSE
## 14      zabrotes subfasciatus      Zabrotes subfasciatus             FALSE
## 15         eurytemora affinis         Eurytemora affinis             FALSE
## 16        drosophila buzzatii        Drosophila buzzatii             FALSE
## 17   callosobruchus chinensis   Callosobruchus chinensis             FALSE
## 18     drosophila bipectinata     Drosophila bipectinata             FALSE
## 19           drosophila hydei           Drosophila hydei             FALSE
## 20 drosophila pseudoananassae Drosophila pseudoananassae             FALSE
## 21       simocephalus vetulus       Simocephalus vetulus             FALSE
## 22              daphnia magna              Daphnia magna             FALSE
## 23              daphnia pulex              Daphnia pulex             FALSE
## 24      brachionus plicatilis      Brachionus plicatilis             FALSE
## 25                danio rerio                Danio rerio             FALSE
##     ott_id is_synonym          flags number_matches
## 1   505714      FALSE                             1
## 2   589555      FALSE sibling_higher              1
## 3  1011010      FALSE                             1
## 4   312452      FALSE                             1
## 5   668394      FALSE sibling_higher              1
## 6   864359      FALSE                             1
## 7   460613      FALSE                             1
## 8   148904      FALSE                             1
## 9   396902      FALSE                             1
## 10   86632      FALSE                             1
## 11  396577      FALSE                             1
## 12    7742      FALSE                             1
## 13  660827      FALSE                             2
## 14  110954      FALSE                             1
## 15  850982      FALSE                             1
## 16  607957      FALSE                             1
## 17  986312      FALSE                             1
## 18  733212      FALSE                             1
## 19  505712      FALSE                             1
## 20  506208      FALSE                             1
## 21  424900      FALSE                             1
## 22  668392      FALSE sibling_higher              1
## 23   59086      FALSE sibling_higher              1
## 24  471703      FALSE                             1
## 25 1005914      FALSE                             1
# Create tree
tree <- tol_induced_subtree(ott_ids = resolved_names$ott_id)
tree$tip.label <- strip_ott_ids(tree$tip.label)  # Remove ott IDs for presentation
# plot(tree, no.margin=TRUE, cex=1)

tree <- multi2di(tree, random = TRUE)  # Resolve polytomy at random, but it matches classification from Cornetti et al. 2019. Molecular Phylogenetics and Evolution; with D. pulex and D. pulicaria being more closely related to eachother than D. magna
phylo_tree <- compute.brlen(tree, method = "Grafen", power = 1)  # Compute branch lengths

# Plot tree
plot(phylo_tree)

# Compute phylogenetic correlation matrix
phylo_matrix <- vcv(phylo_tree, cor = T)  # The vcv function returns a variance-covariance matrix

# Add an additional column for phylogeny
data <- mutate(data, phylogeny = gsub(" ", "_", species), obs = row_number())

# Convert tibble to data frame
data <- as.data.frame(data)

# Rename trait type
data$trait_type <- factor(data$trait_type, levels = c("body_size", "fecundity", "survival"),
    labels = c("Body size", "Fecundity", "Survival"))

# Rename temperature regime
data$warm_cold <- factor(data$warm_cold, levels = c("cold", "warm"), labels = c("Cold",
    "Warm"))

Non-independence due to shared cohorts

Because different traits were sometimes measured on the cohort of animals, we account for this source of non-independence with a variance-covariance matrix to correlate errors of each trait (cf. Noble et al. 2017)

# VCV matrix for lnRR
VCV_lnRR <- vcalc(vi = var_lnRR, cluster = shared_control_ID, rho = 0.5, obs = obs,
    data = data)

# VCV matrix for lnCVR
VCV_lnCVR <- vcalc(vi = var_lnCVR, cluster = shared_control_ID, rho = 0.5, obs = obs,
    data = data)

# VCV matrix for lnVR
VCV_lnVR <- vcalc(vi = var_lnVR, cluster = shared_control_ID, rho = 0.5, obs = obs,
    data = data)

Overview of the dataset

# Summarize overall metrics
overall <- data %>%
    summarise(Group = "Overall", `Number of Studies` = n_distinct(ref), `Number of Species` = n_distinct(species),
        `Number of Effect Sizes` = n_distinct(obs))

# Summarize by trait
by_trait <- data %>%
    group_by(trait_type) %>%
    summarise(Group = paste("Trait -", unique(trait_type)), `Number of Studies` = n_distinct(ref),
        `Number of Species` = n_distinct(species), `Number of Effect Sizes` = n_distinct(obs)) %>%
    ungroup()

# Summarize by temperature regime
by_temperature <- data %>%
    group_by(warm_cold) %>%
    summarise(Group = paste("Temperature regime -", unique(warm_cold)), `Number of Studies` = n_distinct(ref),
        `Number of Species` = n_distinct(species), `Number of Effect Sizes` = n_distinct(obs)) %>%
    ungroup()

# Combine all summaries
table_sample_sizes <- bind_rows(overall, by_trait, by_temperature) %>%
    dplyr::select(-trait_type, -warm_cold)

# Create the table
table_sample_sizes %>%
    kable() %>%
    kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE) %>%
    row_spec(0, background = "white", color = "black", bold = TRUE) %>%
    kable_styling(fixed_thead = TRUE)
Group Number of Studies Number of Species Number of Effect Sizes
Overall 44 25 476
Trait - Body size 27 14 171
Trait - Fecundity 31 22 196
Trait - Survival 22 13 109
Temperature regime - Cold 13 5 95
Temperature regime - Warm 38 23 381

Main meta-analytic models

Note that these models take a substantial amount of time to run. Therefore, these models were ran on the computational cluster Katana, supported by Research Technology Services at UNSW Sydney. Resources needed to run these models are provided in the /pbs/ folder, and the R code used for each model is in the R/models/ folder.

Changes in trait means (lnRR)

Overall model

Model specification

# Model specification
formula <- bf(lnRR ~ trait_type -1 + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnRR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnRR_model_overall <- brm(formula, 
                           family = gaussian(),
                           data = data, 
                           data2 = list(phylo_matrix = phylo_matrix,
                                        VCV_lnRR = VCV_lnRR),
                           prior = prior,
                           control = list(adapt_delta = 0.99, max_treedepth = 15),
                           iter = 4000, 
                           warmup = 2000,
                           chains = 4, 
                           cores = 4, 
                           seed = 123) 

# Save model
saveRDS(lnRR_model_overall, file = "RData/lnRR_model_overall.rds")

Model output

# Load model
lnRR_model_overall <- readRDS("RData/lnRR_model_overall.rds")

# Display model output
summary(lnRR_model_overall)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnRR ~ trait_type - 1 + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnRR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.05      0.01     0.03     0.06 1.00     2428     4079
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.08      0.01     0.07     0.09 1.00     2314     4469
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.02     0.00     0.06 1.00     4112     5342
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.01      0.01     0.00
## sd(trait_typefecundity)                          0.19      0.04     0.13
## sd(trait_typesurvival)                           0.11      0.03     0.06
## cor(trait_typebody_size,trait_typefecundity)    -0.14      0.47    -0.90
## cor(trait_typebody_size,trait_typesurvival)      0.03      0.49    -0.86
## cor(trait_typefecundity,trait_typesurvival)      0.08      0.50    -0.84
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.03 1.00     2591     4316
## sd(trait_typefecundity)                          0.27 1.00     3834     5633
## sd(trait_typesurvival)                           0.17 1.00     4383     5237
## cor(trait_typebody_size,trait_typefecundity)     0.80 1.01      627     1380
## cor(trait_typebody_size,trait_typesurvival)      0.89 1.00     1331     3070
## cor(trait_typefecundity,trait_typesurvival)      0.89 1.00     1888     3903
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.01      0.01     0.00     0.04 1.00     5301     5459
## 
## Regression Coefficients:
##                     Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## trait_typebody_size    -0.00      0.02    -0.04     0.04 1.00     5199     4640
## trait_typefecundity    -0.02      0.04    -0.11     0.06 1.00     5736     6136
## trait_typesurvival      0.02      0.03    -0.04     0.09 1.00     6349     6309
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnRR_model_overall, summary = TRUE)) %>%
    # Rename categorical variables for cleaner display
rownames_to_column(var = "Parameter") %>%
    mutate(Parameter = gsub("trait_type([a-z_]+)", "\\1", Parameter)) %>%
    # Round numbers to 3 decimal points
mutate(across(c(Estimate, Q2.5, Q97.5), ~round(., 3))) %>%
    select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
    kable() %>%
    kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE) %>%
    row_spec(0, background = "white", color = "black", bold = TRUE) %>%
    kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size -0.001 -0.044 0.040
fecundity -0.022 -0.106 0.061
survival 0.023 -0.041 0.090

Heterogeneity analysis

# Extracting the posterior distribution from the model
posterior <- posterior_samples(lnRR_model_overall)

# Calculate measurement error variance
sigma2_v <- sum(1/diag(VCV_lnRR)) * (length(diag(VCV_lnRR))- 1)/(sum(1/diag(VCV_lnRR))^2 - sum((1/diag(VCV_lnRR))^2))

# Calculate the total variance (including the measurement error variance)
var_total <- posterior$sd_experiment_ID__Intercept +
             posterior$sd_obs__Intercept +
             posterior$sd_phylogeny__Intercept +
             posterior$sd_ref__trait_typebody_size +
             posterior$sd_ref__trait_typefecundity +
             posterior$sd_ref__trait_typesurvival +
             posterior$sd_species__Intercept +
             sigma2_v

# Calculate heterogeneity (I2)
I2 <- list(
    I2_total = (var_total - sigma2_v) / var_total, # Total heterogeneity
    I2_study = (posterior$sd_ref__trait_typebody_size + # Heterogeneity explained by study differences
                posterior$sd_ref__trait_typefecundity +
                posterior$sd_ref__trait_typesurvival) / var_total,
    I2_exp = posterior$sd_experiment_ID__Intercept / var_total, # Heterogeneity explained by experiment differences
    I2_sp = posterior$sd_species__Intercept / var_total, # Heterogeneity explained by species differences
    I2_phylo = posterior$sd_phylogeny__Intercept / var_total, # Heterogeneity explained by phylogenetic relatedness
    I2_obs = posterior$sd_obs__Intercept / var_total # Heterogeneity explained by residual variation

)

# Calculate mean and credible intervals 
summary_table <- t(sapply(I2, function(x) {
    c(Mean = 100*round(mean(x),4), 
      ` ` = 100* round(quantile(x, 0.025),4), 
      ` ` = 100*round(quantile(x, 0.975),4))
}))

# Customise table
summary_table <- summary_table %>%
    as.data.frame() %>% 
    rownames_to_column("Variable") %>%
    mutate(
        Variable = recode(Variable,
                          "I2_total"  = "Total",
                          "I2_study"  = "Study",
                          "I2_exp"    = "Experiment",
                          "I2_sp"     = "Species",
                          "I2_phylo"  = "Phylogeny",
                          "I2_obs"    = "Residual")
    ) %>%
    rename(
        lower_HPD = ` .2.5%`,
        upper_HPD = ` .97.5%`
    ) %>%
  mutate(
    Variable = paste0("I<sup>2</sup><sub>", Variable)   # Create a new column with formatted I² and subscripts
  )


# Display table
kable(summary_table, "html", escape = FALSE, 
      col.names = c("Heterogeneity (%)", "Mean", "Lower HPD", "Upper HPD"),
      align = c('l', 'r', 'r', 'r')) %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, width = "200px", bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Heterogeneity (%) Mean Lower HPD Upper HPD
I2Total 99.97 99.97 99.98
I2Study 65.40 55.25 73.94
I2Experiment 9.96 6.52 14.36
I2Species 2.77 0.11 7.91
I2Phylogeny 4.42 0.19 12.53
I2Residual 17.43 13.34 22.34

Data visualisation

# Generate predictions
emmeans_overall <- as.data.frame(emmeans(lnRR_model_overall, ~ trait_type))

emmeans_overall$trait_type <- factor(emmeans_overall$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

# Calculate sample sizes and study counts
sample_sizes_traits <- data %>%
  group_by(trait_type) %>%
  summarise(
    estimates = n(),
    studies = n_distinct(ref)
  )

# Plot
ggplot() +
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75, 
               lwd=1) +
    geom_quasirandom(data = data, # Plot effect sizes, scaled by precision
                     aes(x = trait_type, 
                         y = lnRR, 
                         size = 1/sqrt(var_lnRR)), 
                     fill = "gray75",
                     shape = 21,
                     width = 0.25, 
                     alpha = 0.2) +
    geom_errorbar(data = emmeans_overall,   # Plot the point estimates in white for background
                  aes(ymin = lower.HPD, 
                      ymax = upper.HPD,
                      x = trait_type), 
                  size = 2,
                  width = 0.085,
                  color = "white") +
    geom_point(data = emmeans_overall, # Plot the credible intervals in white for background
               aes(x = trait_type, 
                   y = emmean),
               size = 4.5, 
               stroke = 1.5,
               shape = 21,
               color="white",
               fill = "white") +
    geom_errorbar(data = emmeans_overall,  # Plot the point estimates 
                  aes(x = trait_type, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  size = 1.5,
                  width = 0.075,
                  color = "black") +
    geom_point(data = emmeans_overall, # Plot the credible intervals
               aes(x = trait_type, 
                   y = emmean),
               size = 4,
               shape = 21,
               stroke = 1.5,
               color="black",
               fill = "white") +
    geom_text(data = sample_sizes_traits,  # Sample size annotations 
              aes(x = trait_type, 
                  y = 1.5,
                  label = paste0("k = ", estimates, " (", studies, ")")), 
              hjust = 1, size = 5, show.legend = FALSE) +
    theme_bw() +     # Customize the plot
    labs(y = "lnRR", x = "") +
    scale_size_continuous(range = c(2, 8))+ 
    theme(text = element_text(size = 20, color = "black"),
          legend.title = ggplot2::element_text(size = 16),
          legend.text = ggplot2::element_text(size = 14),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
          panel.border = element_rect(color = "black", size = 1.5)) +
    guides(color = "none", size = "none")+
    coord_flip() + 
    ylim(-1.5, 1.5)

# Save figure
ggsave(file = "fig/lnRR_overall.png", width = 12, height = 7, dpi = 500)

Temperature regime

Model specification

# Model specification
formula <- bf(lnRR ~ trait_type:warm_cold -1 + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnRR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnRR_model_warm_cold <- brm(formula, 
                  family = gaussian(),
                  data = data, 
                  data2 = list(phylo_matrix = phylo_matrix,
                               VCV_lnRR = VCV_lnRR),
                  prior = prior,
                  control = list(adapt_delta = 0.99, max_treedepth = 15),
                  iter = 4000, 
                  warmup = 2000,
                  chains = 4, 
                  cores = 4, 
                  seed = 123) 

# Save model
saveRDS(lnRR_model_warm_cold, file = "RData/lnRR_model_warm_cold.rds")

Model output

# Load model
lnRR_model_warm_cold <- readRDS("RData/lnRR_model_warm_cold.rds")

# Display model output 
summary(lnRR_model_warm_cold)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnRR ~ trait_type:warm_cold - 1 + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnRR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.05      0.01     0.03     0.06 1.00     2199     3535
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.08      0.01     0.07     0.09 1.00     1978     3594
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.02     0.00     0.07 1.00     2828     3846
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.01      0.01     0.00
## sd(trait_typefecundity)                          0.21      0.04     0.14
## sd(trait_typesurvival)                           0.11      0.03     0.06
## cor(trait_typebody_size,trait_typefecundity)    -0.14      0.48    -0.91
## cor(trait_typebody_size,trait_typesurvival)      0.03      0.49    -0.86
## cor(trait_typefecundity,trait_typesurvival)      0.00      0.49    -0.85
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.03 1.00     1823     3152
## sd(trait_typefecundity)                          0.30 1.00     3014     4756
## sd(trait_typesurvival)                           0.18 1.00     2917     3897
## cor(trait_typebody_size,trait_typefecundity)     0.81 1.01      439      934
## cor(trait_typebody_size,trait_typesurvival)      0.88 1.01      922     2295
## cor(trait_typefecundity,trait_typesurvival)      0.85 1.00     1462     2565
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.01      0.01     0.00     0.04 1.00     3404     3916
## 
## Regression Coefficients:
##                                   Estimate Est.Error l-95% CI u-95% CI Rhat
## trait_typebody_size:warm_coldcold     0.01      0.02    -0.04     0.07 1.00
## trait_typefecundity:warm_coldcold    -0.08      0.07    -0.22     0.06 1.00
## trait_typesurvival:warm_coldcold      0.03      0.05    -0.07     0.14 1.00
## trait_typebody_size:warm_coldwarm    -0.01      0.02    -0.05     0.04 1.00
## trait_typefecundity:warm_coldwarm    -0.01      0.05    -0.10     0.09 1.00
## trait_typesurvival:warm_coldwarm      0.02      0.04    -0.05     0.09 1.00
##                                   Bulk_ESS Tail_ESS
## trait_typebody_size:warm_coldcold     1848     2500
## trait_typefecundity:warm_coldcold     3849     5593
## trait_typesurvival:warm_coldcold      3599     4514
## trait_typebody_size:warm_coldwarm     2375     3035
## trait_typefecundity:warm_coldwarm     3592     4745
## trait_typesurvival:warm_coldwarm      3239     4369
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnRR_model_warm_cold, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>% 
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) 0.014 -0.036 0.066
fecundity(cold) -0.080 -0.222 0.056
survival(cold) 0.030 -0.074 0.139
body_size(warm) -0.006 -0.051 0.036
fecundity(warm) -0.006 -0.097 0.089
survival(warm) 0.022 -0.050 0.093

Contrasts

# Generate predictions
emms <- emmeans(lnRR_model_warm_cold, specs = ~warm_cold | trait_type)

# Generate contrasts
contrast(emms, method = "pairwise")
## trait_type = body_size:
##  contrast    estimate lower.HPD upper.HPD
##  cold - warm   0.0205   -0.0114    0.0542
## 
## trait_type = fecundity:
##  contrast    estimate lower.HPD upper.HPD
##  cold - warm  -0.0731   -0.2010    0.0595
## 
## trait_type = survival:
##  contrast    estimate lower.HPD upper.HPD
##  cold - warm   0.0083   -0.0993    0.1137
## 
## Point estimate displayed: median 
## HPD interval probability: 0.95

Data visualisation

# Generate predictions
emmeans_warm_cold <- as.data.frame(emmeans(lnRR_model_warm_cold, 
                                           specs = ~ warm_cold | trait_type))

emmeans_warm_cold$trait_type <- factor(emmeans_warm_cold$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_warm_cold$warm_cold <- factor(emmeans_warm_cold$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Calculate sample sizes and study counts
sample_sizes <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarise(
    estimates = n(),
    studies = n_distinct(ref)
  )

# Plot
ggplot() +
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75, 
               lwd=1) +
    geom_quasirandom(data = data,     # Plot effect sizes, scaled by precision
                     aes(x = trait_type:warm_cold, 
                         y = lnRR, 
                         fill = trait_type:warm_cold, 
                         size = 1/sqrt(var_lnRR)), 
                     color = "black",
                     shape = 21,
                     width = 0.25, 
                     alpha = 0.3) +
    geom_errorbar(data = emmeans_warm_cold,  # Plot the point estimates in white for background
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="white",
                  size = 2.5,
                  width = 0.17) +
    geom_point(data = emmeans_warm_cold,  # Plot the credible intervals in white for background
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 21,
               size = 4, 
               stroke = 2,
               color="white",
               fill = "white") +
    geom_errorbar(data = emmeans_warm_cold, # Plot the point estimates 
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="black",
                  size = 2,
                  width = 0.15) +
    geom_point(data = emmeans_warm_cold, # Plot the credible intervals
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 21,
               size = 3.5, 
               stroke = 2,
               color="black",
               fill = "white") +
    geom_text(data = sample_sizes,  # Sample size annotations 
              aes(x = trait_type:warm_cold, 
                  y = 1.5,
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1, size = 5, show.legend = FALSE) +
    theme_bw() +     # Customize the plot
    labs(y = "lnRR", x = "") +
    scale_size_continuous(range = c(2, 8))+ 
#    scale_fill_manual(values = c("#A5F820", "#73B706",  "#9CEFFC", "#06A2BA",  "#FED2ED", "#B90674"))+
    scale_fill_manual(values = c("#06B4BA", "#E80756", "#06B4BA", "#E80756", "#06B4BA", "#E80756"))+
    scale_color_manual(values = c("Cold" = "#06B4BA", "Warm" = "#E80756")) +  # Text colour
    theme(text = element_text(size = 20, color = "black"),
          legend.title = ggplot2::element_text(size = 16),
          legend.text = ggplot2::element_text(size = 14),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
          panel.border = element_rect(color = "black", size = 1.5)) +
    guides(fill = "none", size = "none")+
    coord_flip() + 
    ylim(-1.5, 1.5)

ggsave(file = "fig/lnRR_warm_cold.png", width = 12, height = 7, dpi = 500)

Assay temperature difference

We calculated the difference between the assay temperature and control temperature (assay_temp_diff) to account for the fact that animals were tested to a different range of temperatures. We also predicted that effects will vary if traits are assayed at colder- or warmer-than-control conditions, depending on the temperature regime. Because the variation in assay temperature generates some nuisance heterogeneity (sensu Noble et al., 2017), the results of subsequent models were provided after controlling for assay temperature differences. In order words, the results of all moderators are conditional on assay temperature, meaning that results are interpretable as the difference between control and selected lines, when animals are tested at the control temperature.

Model specification

# Model specification
formula <- bf(lnRR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnRR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnRR_model_assay_temp_diff <- brm(formula, 
                                  family = gaussian(),
                                  data = data, 
                                  data2 = list(phylo_matrix = phylo_matrix,
                                               VCV_lnRR = VCV_lnRR),
                                  prior = prior,
                                  control = list(adapt_delta = 0.99, max_treedepth = 15),
                                  iter = 4000, 
                                  warmup = 2000,
                                  chains = 4, 
                                  cores = 4, 
                                  seed = 123) 

# Save model
saveRDS(lnRR_model_assay_temp_diff, file = "RData/lnRR_model_assay_temp_diff.rds")

Model output

# Load model
lnRR_model_assay_temp_diff <- readRDS("RData/lnRR_model_assay_temp_diff.rds")

# Display model output
summary(lnRR_model_assay_temp_diff)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnRR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnRR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.01      836     1101
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.05      0.00     0.04     0.06 1.00     1704     3138
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.02     0.00     0.07 1.00     2385     3776
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.01      0.01     0.00
## sd(trait_typefecundity)                          0.21      0.04     0.15
## sd(trait_typesurvival)                           0.13      0.03     0.08
## cor(trait_typebody_size,trait_typefecundity)    -0.13      0.46    -0.89
## cor(trait_typebody_size,trait_typesurvival)      0.08      0.49    -0.84
## cor(trait_typefecundity,trait_typesurvival)     -0.07      0.52    -0.90
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.02 1.00     1547     3228
## sd(trait_typefecundity)                          0.30 1.00     3481     5702
## sd(trait_typesurvival)                           0.20 1.00     3243     5184
## cor(trait_typebody_size,trait_typefecundity)     0.77 1.01      426     1075
## cor(trait_typebody_size,trait_typesurvival)      0.89 1.00      862     2032
## cor(trait_typefecundity,trait_typesurvival)      0.83 1.01      799     2678
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.00     1970     3307
## 
## Regression Coefficients:
##                                                   Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                     0.02      0.02    -0.02
## trait_typefecundity:warm_coldcold                    -0.17      0.06    -0.30
## trait_typesurvival:warm_coldcold                     -0.06      0.06    -0.17
## trait_typebody_size:warm_coldwarm                    -0.00      0.02    -0.04
## trait_typefecundity:warm_coldwarm                    -0.04      0.05    -0.13
## trait_typesurvival:warm_coldwarm                     -0.01      0.04    -0.09
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.00      0.00    -0.00
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.06      0.01    -0.07
## trait_typesurvival:warm_coldcold:assay_temp_diff     -0.04      0.00    -0.05
## trait_typebody_size:warm_coldwarm:assay_temp_diff    -0.00      0.00    -0.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.00      0.00    -0.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.00      0.00    -0.00
##                                                   u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                     0.07 1.00     2228
## trait_typefecundity:warm_coldcold                    -0.04 1.00     3618
## trait_typesurvival:warm_coldcold                      0.05 1.00     3585
## trait_typebody_size:warm_coldwarm                     0.04 1.00     2664
## trait_typefecundity:warm_coldwarm                     0.06 1.00     3070
## trait_typesurvival:warm_coldwarm                      0.06 1.00     3114
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.01 1.00     2104
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.05 1.00     4502
## trait_typesurvival:warm_coldcold:assay_temp_diff     -0.03 1.00     3516
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.00 1.00     3803
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.01 1.00     3198
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.01 1.00     4448
##                                                   Tail_ESS
## trait_typebody_size:warm_coldcold                     3044
## trait_typefecundity:warm_coldcold                     4811
## trait_typesurvival:warm_coldcold                      5338
## trait_typebody_size:warm_coldwarm                     2969
## trait_typefecundity:warm_coldwarm                     4633
## trait_typesurvival:warm_coldwarm                      4161
## trait_typebody_size:warm_coldcold:assay_temp_diff     3599
## trait_typefecundity:warm_coldcold:assay_temp_diff     6330
## trait_typesurvival:warm_coldcold:assay_temp_diff      5524
## trait_typebody_size:warm_coldwarm:assay_temp_diff     4949
## trait_typefecundity:warm_coldwarm:assay_temp_diff     5467
## trait_typesurvival:warm_coldwarm:assay_temp_diff      5841
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnRR_model_assay_temp_diff, summary = TRUE)) %>%
    # Rename categorical variables for cleaner display
rownames_to_column(var = "Parameter") %>%
    mutate(Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)",
        Parameter), Parameter = gsub("trait_type([a-z_]+)\\(warm\\):assay_temp_diff",
        "\\1(warm): assay_temp_diff", Parameter)) %>%
    # Round numbers to 3 decimal points
mutate(across(c(Estimate, Q2.5, Q97.5), ~round(., 3))) %>%
    select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
    kable() %>%
    kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE) %>%
    row_spec(0, background = "white", color = "black", bold = TRUE) %>%
    kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) 0.022 -0.022 0.067
fecundity(cold) -0.167 -0.295 -0.042
survival(cold) -0.062 -0.166 0.052
body_size(warm) -0.001 -0.042 0.041
fecundity(warm) -0.036 -0.126 0.056
survival(warm) -0.010 -0.087 0.062
body_size(cold):assay_temp_diff 0.001 -0.004 0.006
fecundity(cold):assay_temp_diff -0.062 -0.073 -0.052
survival(cold):assay_temp_diff -0.044 -0.053 -0.034
body_size(warm):assay_temp_diff -0.001 -0.004 0.002
fecundity(warm):assay_temp_diff 0.004 -0.003 0.011
survival(warm):assay_temp_diff 0.005 -0.002 0.011

Data visualisation

# Generate predictions
emmeans_assay_temp_diff <- as.data.frame(emmeans(
  lnRR_model_assay_temp_diff,
  specs = ~ assay_temp_diff | trait_type * warm_cold,
  at = list(assay_temp_diff = seq(min(data$assay_temp_diff), max(data$assay_temp_diff), by = 0.5)))
  )

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_assay_temp_diff = min(assay_temp_diff),
    max_assay_temp_diff = max(assay_temp_diff)
  )

emmeans_assay_temp_diff$trait_type <- factor(emmeans_assay_temp_diff$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_assay_temp_diff$warm_cold <- factor(emmeans_assay_temp_diff$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_assay_temp_diff <- emmeans_assay_temp_diff %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    assay_temp_diff >= min_assay_temp_diff,
    assay_temp_diff <= max_assay_temp_diff
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) +  
    geom_vline(xintercept = 0, # Vertical line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) +  
    geom_point(data = data, # Effect sizes, scaled by precision
                  aes(x = assay_temp_diff, 
                      y = lnRR, 
                      size = 1/sqrt(var_lnRR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_assay_temp_diff, # Shaded area for credible intervals
                 aes(x = assay_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_assay_temp_diff,  # Predicted regression line
               aes(y = emmean,
                   x = assay_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) + 
      geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -0.9, -1.3),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  
  facet_wrap(~ trait_type, ncol = 1) + # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Assay temperature difference", y = "lnRR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    ylim(-1.5, 1.5)

ggsave(file = "fig/lnRR_assay_temp_diff.png", width = 12, height = 10, dpi = 500)

Selection temperature

Model specification

# Model specification
formula <- bf(lnRR ~ 0 + trait_type:warm_cold + 
                         trait_type:warm_cold:assay_temp_diff + 
                         trait_type:warm_cold:select_temp_diff + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnRR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnRR_model_sel_temp_diff <- brm(formula, 
                                family = gaussian(),
                                data = data, 
                                data2 = list(phylo_matrix = phylo_matrix,
                                             VCV_lnRR = VCV_lnRR),
                                prior = prior,
                                control = list(adapt_delta = 0.99, max_treedepth = 15),
                                iter = 4000, 
                                warmup = 2000,
                                chains = 4, 
                                cores = 4, 
                                seed = 123) 

# Save model
saveRDS(lnRR_model_sel_temp_diff, file = "RData/lnRR_model_sel_temp_diff.rds")

Model output

# Load model
lnRR_model_sel_temp_diff <- readRDS("RData/lnRR_model_sel_temp_diff.rds")

# Display model output
summary(lnRR_model_sel_temp_diff)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnRR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:select_temp_diff + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnRR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.02      496      672
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.05      0.00     0.04     0.06 1.00     1440     2615
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.02     0.00     0.07 1.00     1936     2888
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.01      0.01     0.00
## sd(trait_typefecundity)                          0.22      0.04     0.16
## sd(trait_typesurvival)                           0.13      0.03     0.08
## cor(trait_typebody_size,trait_typefecundity)    -0.19      0.45    -0.90
## cor(trait_typebody_size,trait_typesurvival)      0.19      0.48    -0.80
## cor(trait_typefecundity,trait_typesurvival)     -0.40      0.53    -0.98
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.03 1.00     1232     2854
## sd(trait_typefecundity)                          0.31 1.00     3355     4947
## sd(trait_typesurvival)                           0.19 1.00     3672     5213
## cor(trait_typebody_size,trait_typefecundity)     0.75 1.02      429      825
## cor(trait_typebody_size,trait_typesurvival)      0.91 1.00      744     1327
## cor(trait_typefecundity,trait_typesurvival)      0.75 1.00      766     1965
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.00     1901     3018
## 
## Regression Coefficients:
##                                                    Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                      0.02      0.03    -0.05
## trait_typefecundity:warm_coldcold                     -0.05      0.14    -0.31
## trait_typesurvival:warm_coldcold                       0.35      0.20    -0.03
## trait_typebody_size:warm_coldwarm                      0.01      0.03    -0.04
## trait_typefecundity:warm_coldwarm                     -0.02      0.07    -0.16
## trait_typesurvival:warm_coldwarm                      -0.03      0.07    -0.16
## trait_typebody_size:warm_coldcold:assay_temp_diff      0.00      0.00    -0.00
## trait_typefecundity:warm_coldcold:assay_temp_diff     -0.06      0.01    -0.07
## trait_typesurvival:warm_coldcold:assay_temp_diff      -0.05      0.00    -0.05
## trait_typebody_size:warm_coldwarm:assay_temp_diff      0.00      0.00    -0.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff      0.00      0.00    -0.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff       0.00      0.00    -0.00
## trait_typebody_size:warm_coldcold:select_temp_diff     0.00      0.00    -0.01
## trait_typefecundity:warm_coldcold:select_temp_diff    -0.02      0.02    -0.06
## trait_typesurvival:warm_coldcold:select_temp_diff     -0.06      0.03    -0.12
## trait_typebody_size:warm_coldwarm:select_temp_diff    -0.00      0.00    -0.01
## trait_typefecundity:warm_coldwarm:select_temp_diff     0.00      0.01    -0.02
## trait_typesurvival:warm_coldwarm:select_temp_diff      0.01      0.01    -0.01
##                                                    u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                      0.08 1.00     1186
## trait_typefecundity:warm_coldcold                      0.22 1.00     3406
## trait_typesurvival:warm_coldcold                       0.75 1.00     2733
## trait_typebody_size:warm_coldwarm                      0.06 1.00     2179
## trait_typefecundity:warm_coldwarm                      0.11 1.00     2379
## trait_typesurvival:warm_coldwarm                       0.11 1.00     1635
## trait_typebody_size:warm_coldcold:assay_temp_diff      0.01 1.00     1615
## trait_typefecundity:warm_coldcold:assay_temp_diff     -0.05 1.00     4516
## trait_typesurvival:warm_coldcold:assay_temp_diff      -0.04 1.00     2879
## trait_typebody_size:warm_coldwarm:assay_temp_diff      0.00 1.00     2302
## trait_typefecundity:warm_coldwarm:assay_temp_diff      0.01 1.00     3142
## trait_typesurvival:warm_coldwarm:assay_temp_diff       0.01 1.00     4091
## trait_typebody_size:warm_coldcold:select_temp_diff     0.01 1.00     1341
## trait_typefecundity:warm_coldcold:select_temp_diff     0.02 1.00     3502
## trait_typesurvival:warm_coldcold:select_temp_diff     -0.01 1.00     2614
## trait_typebody_size:warm_coldwarm:select_temp_diff     0.00 1.00     2142
## trait_typefecundity:warm_coldwarm:select_temp_diff     0.02 1.00     2704
## trait_typesurvival:warm_coldwarm:select_temp_diff      0.02 1.00     1990
##                                                    Tail_ESS
## trait_typebody_size:warm_coldcold                      2116
## trait_typefecundity:warm_coldcold                      5034
## trait_typesurvival:warm_coldcold                       5062
## trait_typebody_size:warm_coldwarm                      2989
## trait_typefecundity:warm_coldwarm                      4122
## trait_typesurvival:warm_coldwarm                       3197
## trait_typebody_size:warm_coldcold:assay_temp_diff      2793
## trait_typefecundity:warm_coldcold:assay_temp_diff      5598
## trait_typesurvival:warm_coldcold:assay_temp_diff       4940
## trait_typebody_size:warm_coldwarm:assay_temp_diff      4053
## trait_typefecundity:warm_coldwarm:assay_temp_diff      4707
## trait_typesurvival:warm_coldwarm:assay_temp_diff       4931
## trait_typebody_size:warm_coldcold:select_temp_diff     2795
## trait_typefecundity:warm_coldcold:select_temp_diff     4593
## trait_typesurvival:warm_coldcold:select_temp_diff      4371
## trait_typebody_size:warm_coldwarm:select_temp_diff     4514
## trait_typefecundity:warm_coldwarm:select_temp_diff     4257
## trait_typesurvival:warm_coldwarm:select_temp_diff      3936
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnRR_model_sel_temp_diff, summary = TRUE)) %>%
    # Rename categorical variables for cleaner display
rownames_to_column(var = "Parameter") %>%
    mutate(Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)",
        Parameter), Parameter = gsub("trait_type([a-z_]+)\\(warm\\):select_temp_diff",
        "\\1(warm): select_temp_diff", Parameter)) %>%
    # Round numbers to 3 decimal points
mutate(across(c(Estimate, Q2.5, Q97.5), ~round(., 3))) %>%
    select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
    kable() %>%
    kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE) %>%
    row_spec(0, background = "white", color = "black", bold = TRUE) %>%
    kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) 0.018 -0.049 0.084
fecundity(cold) -0.048 -0.313 0.222
survival(cold) 0.349 -0.033 0.746
body_size(warm) 0.008 -0.044 0.055
fecundity(warm) -0.024 -0.157 0.115
survival(warm) -0.029 -0.162 0.108
body_size(cold):assay_temp_diff 0.001 -0.004 0.006
fecundity(cold):assay_temp_diff -0.063 -0.073 -0.052
survival(cold):assay_temp_diff -0.045 -0.055 -0.036
body_size(warm):assay_temp_diff 0.000 -0.004 0.004
fecundity(warm):assay_temp_diff 0.004 -0.003 0.011
survival(warm):assay_temp_diff 0.004 -0.003 0.011
body_size(cold):select_temp_diff 0.000 -0.009 0.009
fecundity(cold):select_temp_diff -0.022 -0.064 0.020
survival(cold):select_temp_diff -0.060 -0.116 -0.006
body_size(warm):select_temp_diff -0.002 -0.008 0.004
fecundity(warm):select_temp_diff 0.000 -0.019 0.019
survival(warm):select_temp_diff 0.006 -0.014 0.025

Data visualisation

# Generate predictions
emmeans_sel_temp_diff <- as.data.frame(emmeans(
  lnRR_model_sel_temp_diff,
  specs = ~ select_temp_diff | trait_type * warm_cold,
  at = list(select_temp_diff = seq(min(data$select_temp_diff), max(data$select_temp_diff), by = 0.5),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_select_temp_diff = min(select_temp_diff),
    max_select_temp_diff = max(select_temp_diff)
  )

emmeans_sel_temp_diff$trait_type <- factor(emmeans_sel_temp_diff$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_sel_temp_diff$warm_cold <- factor(emmeans_sel_temp_diff$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_sel_temp_diff <- emmeans_sel_temp_diff %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    select_temp_diff >= min_select_temp_diff,
    select_temp_diff <= max_select_temp_diff
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = select_temp_diff, 
                      y = lnRR, 
                      size = 1/sqrt(var_lnRR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_sel_temp_diff, # Shaded area for credible intervals
                 aes(x = select_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_sel_temp_diff, # Predicted regression line
               aes(y = emmean,
                   x = select_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -0.9, -1.3),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Selection temperature difference", y = "lnRR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    ylim(-1.5, 1.5)

ggsave(file = "fig/lnRR_sel_temp_diff.png", width = 12, height = 7, dpi = 500)

Number of generations of selection

Model specification

# Model specification
formula <- bf(lnRR ~ 0 + trait_type:warm_cold + 
                         trait_type:warm_cold:assay_temp_diff + 
                         trait_type:warm_cold:scale(gen_selection) + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnRR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnRR_model_gen_selection <- brm(formula, 
                                family = gaussian(),
                                data = data, 
                                data2 = list(phylo_matrix = phylo_matrix,
                                             VCV_lnRR = VCV_lnRR),
                                prior = prior,
                                control = list(adapt_delta = 0.99, max_treedepth = 15),
                                iter = 4000, 
                                warmup = 2000,
                                chains = 4, 
                                cores = 4, 
                                seed = 123) 
# Save model
saveRDS(lnRR_model_gen_selection, file = "RData/lnRR_model_gen_selection.rds")

Model output

# Load model
lnRR_model_gen_selection <- readRDS("RData/lnRR_model_gen_selection.rds")

# Display model output 
summary(lnRR_model_gen_selection)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnRR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:scale(gen_selection) + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnRR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.01      617      776
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.05      0.00     0.04     0.06 1.00     1605     2480
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.03      0.02     0.00     0.07 1.00     2219     3539
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.01      0.01     0.00
## sd(trait_typefecundity)                          0.21      0.04     0.15
## sd(trait_typesurvival)                           0.13      0.03     0.08
## cor(trait_typebody_size,trait_typefecundity)    -0.09      0.46    -0.87
## cor(trait_typebody_size,trait_typesurvival)      0.01      0.50    -0.89
## cor(trait_typefecundity,trait_typesurvival)      0.21      0.45    -0.73
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.03 1.00     1513     2634
## sd(trait_typefecundity)                          0.30 1.00     3039     5427
## sd(trait_typesurvival)                           0.20 1.00     3835     5162
## cor(trait_typebody_size,trait_typefecundity)     0.81 1.01      443      913
## cor(trait_typebody_size,trait_typesurvival)      0.87 1.00      740     1751
## cor(trait_typefecundity,trait_typesurvival)      0.88 1.00     1349     2888
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.00     1886     3491
## 
## Regression Coefficients:
##                                                      Estimate Est.Error
## trait_typebody_size:warm_coldcold                        0.02      0.02
## trait_typefecundity:warm_coldcold                       -0.01      0.09
## trait_typesurvival:warm_coldcold                        -0.07      0.08
## trait_typebody_size:warm_coldwarm                       -0.00      0.02
## trait_typefecundity:warm_coldwarm                       -0.04      0.05
## trait_typesurvival:warm_coldwarm                        -0.03      0.05
## trait_typebody_size:warm_coldcold:assay_temp_diff        0.00      0.00
## trait_typefecundity:warm_coldcold:assay_temp_diff       -0.06      0.01
## trait_typesurvival:warm_coldcold:assay_temp_diff        -0.05      0.00
## trait_typebody_size:warm_coldwarm:assay_temp_diff       -0.00      0.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff        0.00      0.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff         0.00      0.00
## trait_typebody_size:warm_coldcold:scalegen_selection     0.01      0.01
## trait_typefecundity:warm_coldcold:scalegen_selection    -0.16      0.06
## trait_typesurvival:warm_coldcold:scalegen_selection     -0.05      0.05
## trait_typebody_size:warm_coldwarm:scalegen_selection     0.00      0.01
## trait_typefecundity:warm_coldwarm:scalegen_selection    -0.01      0.05
## trait_typesurvival:warm_coldwarm:scalegen_selection     -0.09      0.07
##                                                      l-95% CI u-95% CI Rhat
## trait_typebody_size:warm_coldcold                       -0.03     0.06 1.00
## trait_typefecundity:warm_coldcold                       -0.20     0.17 1.00
## trait_typesurvival:warm_coldcold                        -0.22     0.09 1.00
## trait_typebody_size:warm_coldwarm                       -0.05     0.04 1.00
## trait_typefecundity:warm_coldwarm                       -0.13     0.05 1.00
## trait_typesurvival:warm_coldwarm                        -0.12     0.06 1.00
## trait_typebody_size:warm_coldcold:assay_temp_diff       -0.00     0.01 1.00
## trait_typefecundity:warm_coldcold:assay_temp_diff       -0.07    -0.05 1.00
## trait_typesurvival:warm_coldcold:assay_temp_diff        -0.05    -0.04 1.00
## trait_typebody_size:warm_coldwarm:assay_temp_diff       -0.00     0.00 1.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff       -0.00     0.01 1.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff        -0.00     0.01 1.00
## trait_typebody_size:warm_coldcold:scalegen_selection    -0.01     0.02 1.00
## trait_typefecundity:warm_coldcold:scalegen_selection    -0.28    -0.05 1.00
## trait_typesurvival:warm_coldcold:scalegen_selection     -0.15     0.05 1.00
## trait_typebody_size:warm_coldwarm:scalegen_selection    -0.01     0.01 1.00
## trait_typefecundity:warm_coldwarm:scalegen_selection    -0.11     0.08 1.00
## trait_typesurvival:warm_coldwarm:scalegen_selection     -0.23     0.04 1.00
##                                                      Bulk_ESS Tail_ESS
## trait_typebody_size:warm_coldcold                        2264     3007
## trait_typefecundity:warm_coldcold                        4049     5260
## trait_typesurvival:warm_coldcold                         3567     4741
## trait_typebody_size:warm_coldwarm                        2396     2621
## trait_typefecundity:warm_coldwarm                        2960     4425
## trait_typesurvival:warm_coldwarm                         3207     4061
## trait_typebody_size:warm_coldcold:assay_temp_diff        2027     3280
## trait_typefecundity:warm_coldcold:assay_temp_diff        5125     5341
## trait_typesurvival:warm_coldcold:assay_temp_diff         3387     5279
## trait_typebody_size:warm_coldwarm:assay_temp_diff        3289     5032
## trait_typefecundity:warm_coldwarm:assay_temp_diff        3203     5785
## trait_typesurvival:warm_coldwarm:assay_temp_diff         5423     5804
## trait_typebody_size:warm_coldcold:scalegen_selection     2243     3575
## trait_typefecundity:warm_coldcold:scalegen_selection     4317     4963
## trait_typesurvival:warm_coldcold:scalegen_selection      2591     4399
## trait_typebody_size:warm_coldwarm:scalegen_selection     3682     4568
## trait_typefecundity:warm_coldwarm:scalegen_selection     4275     5172
## trait_typesurvival:warm_coldwarm:scalegen_selection      4296     5586
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnRR_model_gen_selection, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((cold|warm)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter),
    # Remove "scale" from gen_selection
    Parameter = gsub("scalegen_selection", "gen_selection", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) 0.015 -0.031 0.061
fecundity(cold) -0.012 -0.199 0.174
survival(cold) -0.067 -0.220 0.087
body_size(warm) -0.005 -0.051 0.037
fecundity(warm) -0.040 -0.134 0.053
survival(warm) -0.028 -0.121 0.062
body_size(cold):assay_temp_diff 0.001 -0.003 0.006
fecundity(cold):assay_temp_diff -0.063 -0.073 -0.052
survival(cold):assay_temp_diff -0.045 -0.055 -0.035
body_size(warm):assay_temp_diff -0.001 -0.004 0.003
fecundity(warm):assay_temp_diff 0.003 -0.004 0.011
survival(warm):assay_temp_diff 0.004 -0.002 0.011
body_size(cold):gen_selection 0.005 -0.012 0.023
fecundity(cold):gen_selection -0.163 -0.283 -0.050
survival(cold):gen_selection -0.048 -0.146 0.051
body_size(warm):gen_selection 0.001 -0.010 0.011
fecundity(warm):gen_selection -0.014 -0.112 0.084
survival(warm):gen_selection -0.090 -0.233 0.045

Data visualisation

# Generate predictions
emmeans_gen_selection <- as.data.frame(emmeans(
  lnRR_model_gen_selection,
  specs = ~ gen_selection | trait_type * warm_cold,
  at = list(gen_selection = seq(min(data$gen_selection), max(data$gen_selection), by = 0.5),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_gen_selection = min(gen_selection),
    max_gen_selection = max(gen_selection)
  )

emmeans_gen_selection$trait_type <- factor(emmeans_gen_selection$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_gen_selection$warm_cold <- factor(emmeans_gen_selection$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_gen_selection <- emmeans_gen_selection %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    gen_selection >= min_gen_selection,
    gen_selection <= max_gen_selection
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = gen_selection, 
                      y = lnRR, 
                      size = 1/sqrt(var_lnRR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_gen_selection, # Shaded area for credible intervals
                 aes(x = gen_selection,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_gen_selection, # Predicted regression line
               aes(y = emmean,
                   x = gen_selection,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -0.9, -1.3),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Number  of generations of selection", y = "lnRR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    ylim(-1.5, 1.5)+
    xlim(0, 150)

ggsave(file = "fig/lnRR_gen_selection.png", width = 12, height = 7, dpi = 500)

Number of generations of common garden

Model specification

# Model specification
formula <- bf(lnRR ~ 0 + trait_type:warm_cold + 
                         trait_type:warm_cold:assay_temp_diff + 
                         trait_type:warm_cold:scale(gen_common_garden) + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnRR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnRR_model_gen_common_garden <- brm(formula, 
                                family = gaussian(),
                                data = data, 
                                data2 = list(phylo_matrix = phylo_matrix,
                                             VCV_lnRR = VCV_lnRR),
                                prior = prior,
                                control = list(adapt_delta = 0.99, max_treedepth = 15),
                                iter = 4000, 
                                warmup = 2000,
                                chains = 4, 
                                cores = 4, 
                                seed = 123) 
# Save model
saveRDS(lnRR_model_gen_common_garden, file = "RData/lnRR_model_gen_common_garden.rds")

Model output

# Load model
lnRR_model_gen_common_garden <- readRDS("RData/lnRR_model_gen_common_garden.rds")

# Display model output 
summary(lnRR_model_gen_common_garden)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnRR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:scale(gen_common_garden) + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnRR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.01      733      688
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.05      0.00     0.04     0.06 1.00     1435     3238
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.03      0.02     0.00     0.07 1.00     2223     3481
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.01      0.01     0.00
## sd(trait_typefecundity)                          0.20      0.03     0.14
## sd(trait_typesurvival)                           0.50      0.21     0.14
## cor(trait_typebody_size,trait_typefecundity)    -0.14      0.44    -0.89
## cor(trait_typebody_size,trait_typesurvival)      0.10      0.48    -0.83
## cor(trait_typefecundity,trait_typesurvival)     -0.48      0.34    -0.92
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.03 1.00     1642     3193
## sd(trait_typefecundity)                          0.28 1.00     3616     5629
## sd(trait_typesurvival)                           0.95 1.01      578      988
## cor(trait_typebody_size,trait_typefecundity)     0.78 1.01      438      782
## cor(trait_typebody_size,trait_typesurvival)      0.89 1.01      579     1488
## cor(trait_typefecundity,trait_typesurvival)      0.33 1.00     1661     3238
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.00     2154     3219
## 
## Regression Coefficients:
##                                                          Estimate Est.Error
## trait_typebody_size:warm_coldcold                            0.02      0.02
## trait_typefecundity:warm_coldcold                           -0.17      0.06
## trait_typesurvival:warm_coldcold                             0.12      0.13
## trait_typebody_size:warm_coldwarm                           -0.00      0.02
## trait_typefecundity:warm_coldwarm                           -0.04      0.05
## trait_typesurvival:warm_coldwarm                             0.10      0.12
## trait_typebody_size:warm_coldcold:assay_temp_diff            0.00      0.00
## trait_typefecundity:warm_coldcold:assay_temp_diff           -0.06      0.01
## trait_typesurvival:warm_coldcold:assay_temp_diff            -0.05      0.00
## trait_typebody_size:warm_coldwarm:assay_temp_diff           -0.00      0.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff            0.00      0.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff             0.00      0.00
## trait_typebody_size:warm_coldcold:scalegen_common_garden    -0.04      0.06
## trait_typefecundity:warm_coldcold:scalegen_common_garden     0.36      0.24
## trait_typesurvival:warm_coldcold:scalegen_common_garden      1.84      0.80
## trait_typebody_size:warm_coldwarm:scalegen_common_garden     0.03      0.05
## trait_typefecundity:warm_coldwarm:scalegen_common_garden     0.02      0.01
## trait_typesurvival:warm_coldwarm:scalegen_common_garden      2.07      0.77
##                                                          l-95% CI u-95% CI Rhat
## trait_typebody_size:warm_coldcold                           -0.03     0.06 1.00
## trait_typefecundity:warm_coldcold                           -0.29    -0.05 1.00
## trait_typesurvival:warm_coldcold                            -0.11     0.42 1.00
## trait_typebody_size:warm_coldwarm                           -0.05     0.04 1.00
## trait_typefecundity:warm_coldwarm                           -0.13     0.05 1.00
## trait_typesurvival:warm_coldwarm                            -0.12     0.35 1.00
## trait_typebody_size:warm_coldcold:assay_temp_diff           -0.00     0.01 1.00
## trait_typefecundity:warm_coldcold:assay_temp_diff           -0.07    -0.05 1.00
## trait_typesurvival:warm_coldcold:assay_temp_diff            -0.05    -0.04 1.00
## trait_typebody_size:warm_coldwarm:assay_temp_diff           -0.00     0.00 1.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff           -0.00     0.01 1.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff            -0.00     0.01 1.00
## trait_typebody_size:warm_coldcold:scalegen_common_garden    -0.15     0.07 1.00
## trait_typefecundity:warm_coldcold:scalegen_common_garden    -0.12     0.84 1.00
## trait_typesurvival:warm_coldcold:scalegen_common_garden      0.29     3.30 1.01
## trait_typebody_size:warm_coldwarm:scalegen_common_garden    -0.06     0.13 1.00
## trait_typefecundity:warm_coldwarm:scalegen_common_garden    -0.01     0.05 1.00
## trait_typesurvival:warm_coldwarm:scalegen_common_garden      0.56     3.46 1.01
##                                                          Bulk_ESS Tail_ESS
## trait_typebody_size:warm_coldcold                            2459     2892
## trait_typefecundity:warm_coldcold                            3326     4513
## trait_typesurvival:warm_coldcold                             1766     3486
## trait_typebody_size:warm_coldwarm                            2575     2515
## trait_typefecundity:warm_coldwarm                            2905     4016
## trait_typesurvival:warm_coldwarm                             2261     3265
## trait_typebody_size:warm_coldcold:assay_temp_diff            2321     3484
## trait_typefecundity:warm_coldcold:assay_temp_diff            5260     5568
## trait_typesurvival:warm_coldcold:assay_temp_diff             3092     3982
## trait_typebody_size:warm_coldwarm:assay_temp_diff            3653     4438
## trait_typefecundity:warm_coldwarm:assay_temp_diff            3689     5846
## trait_typesurvival:warm_coldwarm:assay_temp_diff             4614     5578
## trait_typebody_size:warm_coldcold:scalegen_common_garden     3148     4107
## trait_typefecundity:warm_coldcold:scalegen_common_garden     7731     5761
## trait_typesurvival:warm_coldcold:scalegen_common_garden       655     1522
## trait_typebody_size:warm_coldwarm:scalegen_common_garden     2303     3862
## trait_typefecundity:warm_coldwarm:scalegen_common_garden     5577     4857
## trait_typesurvival:warm_coldwarm:scalegen_common_garden       628     1296
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnRR_model_gen_common_garden, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((cold|warm)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter),
    # Remove "scale" from gen_common_garden
    Parameter = gsub("scalegen_common_garden", "gen_common_garden", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) 0.016 -0.030 0.061
fecundity(cold) -0.170 -0.295 -0.048
survival(cold) 0.125 -0.107 0.416
body_size(warm) -0.003 -0.049 0.039
fecundity(warm) -0.043 -0.133 0.047
survival(warm) 0.097 -0.118 0.354
body_size(cold):assay_temp_diff 0.001 -0.003 0.006
fecundity(cold):assay_temp_diff -0.062 -0.073 -0.052
survival(cold):assay_temp_diff -0.045 -0.055 -0.036
body_size(warm):assay_temp_diff 0.000 -0.004 0.003
fecundity(warm):assay_temp_diff 0.004 -0.003 0.012
survival(warm):assay_temp_diff 0.002 -0.005 0.010
body_size(cold):gen_common_garden -0.042 -0.150 0.073
fecundity(cold):gen_common_garden 0.357 -0.118 0.839
survival(cold):gen_common_garden 1.836 0.292 3.301
body_size(warm):gen_common_garden 0.031 -0.060 0.128
fecundity(warm):gen_common_garden 0.018 -0.011 0.046
survival(warm):gen_common_garden 2.069 0.558 3.455

Data visualisation

# Generate predictions
emmeans_gen_common_garden <- as.data.frame(emmeans(
  lnRR_model_gen_common_garden,
  specs = ~ gen_common_garden | trait_type * warm_cold,
  at = list(gen_common_garden = seq(min(data$gen_common_garden), max(data$gen_common_garden), by = 1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0


# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_gen_common_garden = min(gen_common_garden),
    max_gen_common_garden = max(gen_common_garden)
  )

emmeans_gen_common_garden$trait_type <- factor(emmeans_gen_common_garden$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_gen_common_garden$warm_cold <- factor(emmeans_gen_common_garden$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_gen_common_garden <- emmeans_gen_common_garden %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    gen_common_garden >= min_gen_common_garden,
    gen_common_garden <= max_gen_common_garden
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = gen_common_garden, 
                      y = lnRR, 
                      size = 1/sqrt(var_lnRR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_gen_common_garden, # Shaded area for credible intervals
                 aes(x = gen_common_garden,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_gen_common_garden, # Predicted regression line
               aes(y = emmean,
                   x = gen_common_garden,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -0.9, -1.3),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Number of generations of common garden", y = "lnRR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-1.5, 1.5),
                    xlim = c(0, 12))

ggsave(file = "fig/lnRR_gen_common_garden.png", width = 12, height = 7, dpi = 500)

Population size

Model specification

# Model specification
formula <- bf(lnRR ~ 0 + trait_type:warm_cold + 
                         trait_type:warm_cold:assay_temp_diff + 
                         trait_type:warm_cold:scale(pop_size) + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnRR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnRR_model_pop_size <- brm(formula, 
                                family = gaussian(),
                                data = data, 
                                data2 = list(phylo_matrix = phylo_matrix,
                                             VCV_lnRR = VCV_lnRR),
                                prior = prior,
                                control = list(adapt_delta = 0.99, max_treedepth = 15),
                                iter = 4000, 
                                warmup = 2000,
                                chains = 4, 
                                cores = 4, 
                                seed = 123) 
# Save model
saveRDS(lnRR_model_pop_size, file = "RData/lnRR_model_pop_size.rds")

Model output

# Load model
lnRR_model_pop_size <- readRDS("RData/lnRR_model_pop_size.rds")

# Display model output 
summary(lnRR_model_pop_size)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnRR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:scale(pop_size) + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnRR) 
##    Data: data (Number of observations: 426) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 79) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.01      0.01     0.00     0.03 1.00      743     1669
## 
## ~obs (Number of levels: 426) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.05      0.00     0.04     0.05 1.00     1926     3742
## 
## ~phylogeny (Number of levels: 22) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.03      0.02     0.00     0.07 1.00     2664     3599
## 
## ~ref (Number of levels: 41) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.01      0.01     0.00
## sd(trait_typefecundity)                          0.23      0.04     0.16
## sd(trait_typesurvival)                           0.13      0.03     0.08
## cor(trait_typebody_size,trait_typefecundity)    -0.07      0.46    -0.88
## cor(trait_typebody_size,trait_typesurvival)      0.18      0.49    -0.81
## cor(trait_typefecundity,trait_typesurvival)      0.02      0.48    -0.83
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.03 1.00     1496     3181
## sd(trait_typefecundity)                          0.33 1.00     2900     5491
## sd(trait_typesurvival)                           0.21 1.00     3678     4857
## cor(trait_typebody_size,trait_typefecundity)     0.83 1.01      381      878
## cor(trait_typebody_size,trait_typesurvival)      0.92 1.01      904     1910
## cor(trait_typefecundity,trait_typesurvival)      0.85 1.00     1220     2830
## 
## ~species (Number of levels: 22) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.00     2638     3700
## 
## Regression Coefficients:
##                                                   Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                     0.02      0.02    -0.03
## trait_typefecundity:warm_coldcold                    -0.25      0.08    -0.41
## trait_typesurvival:warm_coldcold                     -0.13      0.07    -0.25
## trait_typebody_size:warm_coldwarm                    -0.00      0.02    -0.05
## trait_typefecundity:warm_coldwarm                    -0.04      0.05    -0.15
## trait_typesurvival:warm_coldwarm                      0.01      0.04    -0.07
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.00      0.00    -0.00
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.06      0.01    -0.07
## trait_typesurvival:warm_coldcold:assay_temp_diff     -0.05      0.00    -0.06
## trait_typebody_size:warm_coldwarm:assay_temp_diff    -0.00      0.00    -0.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.01      0.00    -0.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.00      0.00    -0.00
## trait_typebody_size:warm_coldcold:scalepop_size      -0.00      0.01    -0.02
## trait_typefecundity:warm_coldcold:scalepop_size       0.09      0.07    -0.05
## trait_typesurvival:warm_coldcold:scalepop_size        0.12      0.06     0.00
## trait_typebody_size:warm_coldwarm:scalepop_size      -0.01      0.01    -0.02
## trait_typefecundity:warm_coldwarm:scalepop_size      -0.00      0.05    -0.11
## trait_typesurvival:warm_coldwarm:scalepop_size        0.02      0.03    -0.04
##                                                   u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                     0.06 1.00     2728
## trait_typefecundity:warm_coldcold                    -0.10 1.00     4540
## trait_typesurvival:warm_coldcold                      0.01 1.00     4855
## trait_typebody_size:warm_coldwarm                     0.04 1.00     2932
## trait_typefecundity:warm_coldwarm                     0.07 1.00     3774
## trait_typesurvival:warm_coldwarm                      0.09 1.00     3978
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.01 1.00     2115
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.05 1.00     5182
## trait_typesurvival:warm_coldcold:assay_temp_diff     -0.04 1.00     4594
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.00 1.00     3215
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.01 1.00     6241
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.01 1.00     6143
## trait_typebody_size:warm_coldcold:scalepop_size       0.02 1.00     2081
## trait_typefecundity:warm_coldcold:scalepop_size       0.22 1.00     4179
## trait_typesurvival:warm_coldcold:scalepop_size        0.24 1.00     4129
## trait_typebody_size:warm_coldwarm:scalepop_size       0.01 1.00     2585
## trait_typefecundity:warm_coldwarm:scalepop_size       0.10 1.00     4105
## trait_typesurvival:warm_coldwarm:scalepop_size        0.09 1.00     4556
##                                                   Tail_ESS
## trait_typebody_size:warm_coldcold                     3521
## trait_typefecundity:warm_coldcold                     5721
## trait_typesurvival:warm_coldcold                      5641
## trait_typebody_size:warm_coldwarm                     3273
## trait_typefecundity:warm_coldwarm                     5096
## trait_typesurvival:warm_coldwarm                      4892
## trait_typebody_size:warm_coldcold:assay_temp_diff     3181
## trait_typefecundity:warm_coldcold:assay_temp_diff     5854
## trait_typesurvival:warm_coldcold:assay_temp_diff      5891
## trait_typebody_size:warm_coldwarm:assay_temp_diff     4866
## trait_typefecundity:warm_coldwarm:assay_temp_diff     5471
## trait_typesurvival:warm_coldwarm:assay_temp_diff      6159
## trait_typebody_size:warm_coldcold:scalepop_size       3983
## trait_typefecundity:warm_coldcold:scalepop_size       4860
## trait_typesurvival:warm_coldcold:scalepop_size        4835
## trait_typebody_size:warm_coldwarm:scalepop_size       3997
## trait_typefecundity:warm_coldwarm:scalepop_size       4570
## trait_typesurvival:warm_coldwarm:scalepop_size        4389
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnRR_model_pop_size, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((cold|warm)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter),
    # Remove "scale" from pop_size
    Parameter = gsub("scalepop_size", "pop_size", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) 0.015 -0.032 0.062
fecundity(cold) -0.252 -0.408 -0.102
survival(cold) -0.125 -0.254 0.007
body_size(warm) -0.001 -0.046 0.041
fecundity(warm) -0.042 -0.149 0.067
survival(warm) 0.006 -0.072 0.087
body_size(cold):assay_temp_diff 0.001 -0.004 0.005
fecundity(cold):assay_temp_diff -0.064 -0.074 -0.054
survival(cold):assay_temp_diff -0.046 -0.055 -0.037
body_size(warm):assay_temp_diff -0.001 -0.004 0.002
fecundity(warm):assay_temp_diff 0.007 -0.001 0.015
survival(warm):assay_temp_diff 0.004 -0.002 0.010
body_size(cold):pop_size 0.000 -0.019 0.019
fecundity(cold):pop_size 0.085 -0.048 0.221
survival(cold):pop_size 0.119 0.004 0.244
body_size(warm):pop_size -0.007 -0.021 0.008
fecundity(warm):pop_size -0.001 -0.106 0.098
survival(warm):pop_size 0.025 -0.042 0.093

Data visualisation

# Generate predictions
emmeans_pop_size <- as.data.frame(emmeans(
  lnRR_model_pop_size,
  specs = ~ pop_size | trait_type * warm_cold,
  at = list(pop_size = seq(min(data$pop_size, na.rm=T), max(data$pop_size, na.rm=T), by = 50),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0


# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_pop_size = min(pop_size, na.rm=T),
    max_pop_size = max(pop_size, na.rm=T)
  )

emmeans_pop_size$trait_type <- factor(emmeans_pop_size$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_pop_size$warm_cold <- factor(emmeans_pop_size$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_pop_size <- emmeans_pop_size %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    pop_size >= min_pop_size,
    pop_size <= max_pop_size
  )

# Calculate sample sizes and study counts for population size
sample_sizes_pop_size <- data %>%
  filter(is.na(pop_size)==FALSE) %>% 
  group_by(trait_type, warm_cold) %>%
  summarise(
    estimates = n(),
    studies = n_distinct(ref)
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = pop_size, 
                      y = lnRR, 
                      size = 1/sqrt(var_lnRR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_pop_size, # Shaded area for credible intervals
                 aes(x = pop_size,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_pop_size, # Predicted regression line
               aes(y = emmean,
                   x = pop_size,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes_pop_size, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -0.9, -1.3),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Population size", y = "lnRR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-1.5, 1.5))

ggsave(file = "fig/lnRR_pop_size.png", width = 12, height = 7, dpi = 500)

All moderators

Model specification

# Model specification
formula <- bf(lnRR ~ 0 + trait_type:warm_cold + 
                trait_type:warm_cold:assay_temp_diff + 
                trait_type:warm_cold:scale(select_temp_diff) +
                trait_type:warm_cold:scale(gen_selection) + 
                trait_type:warm_cold:scale(gen_common_garden) + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnRR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnRR_model_all_moderators <- brm(formula, 
                                  family = gaussian(),
                                  data = data, 
                                  data2 = list(phylo_matrix = phylo_matrix,
                                               VCV_lnRR = VCV_lnRR),
                                  prior = prior,
                                  control = list(adapt_delta = 0.99, max_treedepth = 15),
                                  iter = 4000, 
                                  warmup = 2000,
                                  chains = 4, 
                                  cores = 4, 
                                  seed = 123) 

# Save model
saveRDS(lnRR_model_all_moderators, file = "RData/lnRR_model_all_moderators.rds")

Model output

# Load model
lnRR_model_all_moderators <- readRDS("RData/lnRR_model_all_moderators.rds")

# Display model output 
summary(lnRR_model_all_moderators)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnRR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:scale(select_temp_diff) + trait_type:warm_cold:scale(gen_selection) + trait_type:warm_cold:scale(gen_common_garden) + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnRR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.00      748     1068
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.05      0.00     0.04     0.06 1.00     1779     3050
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.03      0.02     0.00     0.07 1.00     2434     3885
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.01      0.01     0.00
## sd(trait_typefecundity)                          0.21      0.04     0.14
## sd(trait_typesurvival)                           0.64      0.21     0.24
## cor(trait_typebody_size,trait_typefecundity)    -0.14      0.46    -0.89
## cor(trait_typebody_size,trait_typesurvival)      0.08      0.48    -0.83
## cor(trait_typefecundity,trait_typesurvival)     -0.40      0.34    -0.91
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.03 1.00     1776     3327
## sd(trait_typefecundity)                          0.30 1.00     3633     5612
## sd(trait_typesurvival)                           1.10 1.00     1279     1252
## cor(trait_typebody_size,trait_typefecundity)     0.81 1.02      494     1049
## cor(trait_typebody_size,trait_typesurvival)      0.89 1.01      551     1374
## cor(trait_typefecundity,trait_typesurvival)      0.38 1.00     2284     3612
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.00     2569     4362
## 
## Regression Coefficients:
##                                                          Estimate Est.Error
## trait_typebody_size:warm_coldcold                            0.01      0.02
## trait_typefecundity:warm_coldcold                           -0.04      0.10
## trait_typesurvival:warm_coldcold                            -0.07      0.29
## trait_typebody_size:warm_coldwarm                           -0.01      0.02
## trait_typefecundity:warm_coldwarm                           -0.04      0.05
## trait_typesurvival:warm_coldwarm                             0.05      0.18
## trait_typebody_size:warm_coldcold:assay_temp_diff            0.00      0.00
## trait_typefecundity:warm_coldcold:assay_temp_diff           -0.06      0.01
## trait_typesurvival:warm_coldcold:assay_temp_diff            -0.05      0.00
## trait_typebody_size:warm_coldwarm:assay_temp_diff            0.00      0.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff            0.00      0.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff             0.00      0.00
## trait_typebody_size:warm_coldcold:scaleselect_temp_diff      0.01      0.02
## trait_typefecundity:warm_coldcold:scaleselect_temp_diff     -0.03      0.08
## trait_typesurvival:warm_coldcold:scaleselect_temp_diff      -0.29      0.78
## trait_typebody_size:warm_coldwarm:scaleselect_temp_diff     -0.01      0.01
## trait_typefecundity:warm_coldwarm:scaleselect_temp_diff      0.01      0.03
## trait_typesurvival:warm_coldwarm:scaleselect_temp_diff       0.01      0.09
## trait_typebody_size:warm_coldcold:scalegen_selection         0.00      0.01
## trait_typefecundity:warm_coldcold:scalegen_selection        -0.14      0.07
## trait_typesurvival:warm_coldcold:scalegen_selection          0.30      0.41
## trait_typebody_size:warm_coldwarm:scalegen_selection         0.00      0.01
## trait_typefecundity:warm_coldwarm:scalegen_selection        -0.02      0.05
## trait_typesurvival:warm_coldwarm:scalegen_selection         -0.22      0.25
## trait_typebody_size:warm_coldcold:scalegen_common_garden    -0.05      0.06
## trait_typefecundity:warm_coldcold:scalegen_common_garden     0.11      0.30
## trait_typesurvival:warm_coldcold:scalegen_common_garden      2.89      1.23
## trait_typebody_size:warm_coldwarm:scalegen_common_garden     0.03      0.05
## trait_typefecundity:warm_coldwarm:scalegen_common_garden     0.02      0.02
## trait_typesurvival:warm_coldwarm:scalegen_common_garden      2.56      0.67
##                                                          l-95% CI u-95% CI Rhat
## trait_typebody_size:warm_coldcold                           -0.03     0.06 1.00
## trait_typefecundity:warm_coldcold                           -0.23     0.15 1.00
## trait_typesurvival:warm_coldcold                            -0.66     0.51 1.00
## trait_typebody_size:warm_coldwarm                           -0.06     0.04 1.00
## trait_typefecundity:warm_coldwarm                           -0.14     0.06 1.00
## trait_typesurvival:warm_coldwarm                            -0.31     0.43 1.00
## trait_typebody_size:warm_coldcold:assay_temp_diff           -0.00     0.01 1.00
## trait_typefecundity:warm_coldcold:assay_temp_diff           -0.07    -0.05 1.00
## trait_typesurvival:warm_coldcold:assay_temp_diff            -0.05    -0.04 1.00
## trait_typebody_size:warm_coldwarm:assay_temp_diff           -0.00     0.00 1.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff           -0.00     0.01 1.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff            -0.00     0.01 1.00
## trait_typebody_size:warm_coldcold:scaleselect_temp_diff     -0.03     0.04 1.00
## trait_typefecundity:warm_coldcold:scaleselect_temp_diff     -0.19     0.12 1.00
## trait_typesurvival:warm_coldcold:scaleselect_temp_diff      -1.89     1.27 1.00
## trait_typebody_size:warm_coldwarm:scaleselect_temp_diff     -0.03     0.01 1.00
## trait_typefecundity:warm_coldwarm:scaleselect_temp_diff     -0.05     0.06 1.00
## trait_typesurvival:warm_coldwarm:scaleselect_temp_diff      -0.17     0.19 1.00
## trait_typebody_size:warm_coldcold:scalegen_selection        -0.02     0.02 1.00
## trait_typefecundity:warm_coldcold:scalegen_selection        -0.29    -0.01 1.00
## trait_typesurvival:warm_coldcold:scalegen_selection         -0.48     1.17 1.00
## trait_typebody_size:warm_coldwarm:scalegen_selection        -0.01     0.01 1.00
## trait_typefecundity:warm_coldwarm:scalegen_selection        -0.12     0.09 1.00
## trait_typesurvival:warm_coldwarm:scalegen_selection         -0.70     0.27 1.00
## trait_typebody_size:warm_coldcold:scalegen_common_garden    -0.17     0.07 1.00
## trait_typefecundity:warm_coldcold:scalegen_common_garden    -0.47     0.69 1.00
## trait_typesurvival:warm_coldcold:scalegen_common_garden      0.69     5.46 1.00
## trait_typebody_size:warm_coldwarm:scalegen_common_garden    -0.06     0.13 1.00
## trait_typefecundity:warm_coldwarm:scalegen_common_garden    -0.01     0.05 1.00
## trait_typesurvival:warm_coldwarm:scalegen_common_garden      0.98     3.71 1.00
##                                                          Bulk_ESS Tail_ESS
## trait_typebody_size:warm_coldcold                            2445     2573
## trait_typefecundity:warm_coldcold                            4443     5130
## trait_typesurvival:warm_coldcold                             3462     3694
## trait_typebody_size:warm_coldwarm                            2788     2776
## trait_typefecundity:warm_coldwarm                            3540     4041
## trait_typesurvival:warm_coldwarm                             3347     3847
## trait_typebody_size:warm_coldcold:assay_temp_diff            2230     3243
## trait_typefecundity:warm_coldcold:assay_temp_diff            4978     5833
## trait_typesurvival:warm_coldcold:assay_temp_diff             3983     5028
## trait_typebody_size:warm_coldwarm:assay_temp_diff            3888     5504
## trait_typefecundity:warm_coldwarm:assay_temp_diff            3743     5686
## trait_typesurvival:warm_coldwarm:assay_temp_diff             6812     5865
## trait_typebody_size:warm_coldcold:scaleselect_temp_diff      1988     3222
## trait_typefecundity:warm_coldcold:scaleselect_temp_diff      5040     4919
## trait_typesurvival:warm_coldcold:scaleselect_temp_diff       2707     3185
## trait_typebody_size:warm_coldwarm:scaleselect_temp_diff      3932     4928
## trait_typefecundity:warm_coldwarm:scaleselect_temp_diff      5447     5614
## trait_typesurvival:warm_coldwarm:scaleselect_temp_diff       5039     5053
## trait_typebody_size:warm_coldcold:scalegen_selection         2539     3874
## trait_typefecundity:warm_coldcold:scalegen_selection         4291     4598
## trait_typesurvival:warm_coldcold:scalegen_selection          2585     3364
## trait_typebody_size:warm_coldwarm:scalegen_selection         4828     5062
## trait_typefecundity:warm_coldwarm:scalegen_selection         4797     4678
## trait_typesurvival:warm_coldwarm:scalegen_selection          4011     4623
## trait_typebody_size:warm_coldcold:scalegen_common_garden     3429     4295
## trait_typefecundity:warm_coldcold:scalegen_common_garden     5690     5471
## trait_typesurvival:warm_coldcold:scalegen_common_garden      1730     2239
## trait_typebody_size:warm_coldwarm:scalegen_common_garden     3496     4478
## trait_typefecundity:warm_coldwarm:scalegen_common_garden     6349     5572
## trait_typesurvival:warm_coldwarm:scalegen_common_garden      1677     1288
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnRR_model_all_moderators, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((cold|warm)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter),
    # Remove "scale" from all moderator variables
    Parameter = gsub("scale", "", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) 0.015 -0.035 0.064
fecundity(cold) -0.045 -0.235 0.150
survival(cold) -0.071 -0.662 0.508
body_size(warm) -0.006 -0.055 0.038
fecundity(warm) -0.042 -0.142 0.060
survival(warm) 0.054 -0.307 0.431
body_size(cold):assay_temp_diff 0.002 -0.003 0.008
fecundity(cold):assay_temp_diff -0.063 -0.073 -0.052
survival(cold):assay_temp_diff -0.045 -0.055 -0.035
body_size(warm):assay_temp_diff 0.001 -0.003 0.005
fecundity(warm):assay_temp_diff 0.004 -0.003 0.012
survival(warm):assay_temp_diff 0.002 -0.005 0.009
body_size(cold):select_temp_diff 0.005 -0.027 0.039
fecundity(cold):select_temp_diff -0.032 -0.190 0.120
survival(cold):select_temp_diff -0.289 -1.893 1.267
body_size(warm):select_temp_diff -0.008 -0.028 0.012
fecundity(warm):select_temp_diff 0.006 -0.050 0.064
survival(warm):select_temp_diff 0.012 -0.174 0.194
body_size(cold):gen_selection 0.001 -0.021 0.021
fecundity(cold):gen_selection -0.144 -0.287 -0.009
survival(cold):gen_selection 0.300 -0.480 1.174
body_size(warm):gen_selection 0.000 -0.010 0.011
fecundity(warm):gen_selection -0.018 -0.123 0.086
survival(warm):gen_selection -0.217 -0.700 0.274
body_size(cold):gen_common_garden -0.052 -0.169 0.071
fecundity(cold):gen_common_garden 0.110 -0.468 0.690
survival(cold):gen_common_garden 2.891 0.690 5.460
body_size(warm):gen_common_garden 0.034 -0.058 0.132
fecundity(warm):gen_common_garden 0.019 -0.012 0.049
survival(warm):gen_common_garden 2.564 0.983 3.713
# Generate predicted values at different assay temperatures
emmeans_full_model <- as.data.frame(emmeans(
  lnRR_model_all_moderators,
  specs = ~ assay_temp_diff * select_temp_diff * gen_selection * gen_common_garden | trait_type * warm_cold,
  at = list(assay_temp_diff = c(-8.5, -4, 0, 4, 5, -5, 17, 20)) # Predict at unique min, control, max values
))

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_assay = min(assay_temp_diff),
    max_assay = max(assay_temp_diff),
    control_assay = 0
  )

emmeans_full_model$trait_type <- factor(emmeans_full_model$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_full_model$warm_cold <- factor(emmeans_full_model$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_full_model %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    assay_temp_diff == min_assay |
    assay_temp_diff == max_assay |
    assay_temp_diff == control_assay) %>% 
    dplyr::select(-min_assay, -max_assay, -control_assay) %>% 
    mutate(percentage_change = (exp(emmean) - 1) * 100,
           percentage_lower_HPD = (exp(lower.HPD) - 1) * 100,
           percentage_upper_HPD = (exp(upper.HPD) - 1) * 100) %>%
  mutate(across(c(emmean, 
                  lower.HPD, 
                  upper.HPD, 
                  percentage_change,
                  percentage_lower_HPD, 
                  percentage_upper_HPD), ~ round(., 3))) %>%   # Round numbers to 3 decimal points
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
assay_temp_diff select_temp_diff gen_selection gen_common_garden trait_type warm_cold emmean lower.HPD upper.HPD percentage_change percentage_lower_HPD percentage_upper_HPD
-8.5 5.64645 29.0084 2.710084 Body size Cold -0.002 -0.068 0.063 -0.174 -6.570 6.513
0.0 5.64645 29.0084 2.710084 Body size Cold 0.015 -0.033 0.066 1.532 -3.216 6.847
5.0 5.64645 29.0084 2.710084 Body size Cold 0.026 -0.028 0.083 2.583 -2.791 8.605
-8.5 5.64645 29.0084 2.710084 Fecundity Cold 0.492 0.287 0.693 63.516 33.287 100.029
0.0 5.64645 29.0084 2.710084 Fecundity Cold -0.045 -0.235 0.150 -4.374 -20.917 16.194
5.0 5.64645 29.0084 2.710084 Fecundity Cold -0.360 -0.565 -0.155 -30.208 -43.189 -14.385
-8.5 5.64645 29.0084 2.710084 Survival Cold 0.315 -0.258 0.919 36.989 -22.732 150.565
0.0 5.64645 29.0084 2.710084 Survival Cold -0.069 -0.679 0.491 -6.711 -49.275 63.319
4.0 5.64645 29.0084 2.710084 Survival Cold -0.250 -0.870 0.298 -22.093 -58.093 34.776
0.0 5.64645 29.0084 2.710084 Body size Warm -0.006 -0.053 0.039 -0.591 -5.122 4.027
-5.0 5.64645 29.0084 2.710084 Body size Warm -0.010 -0.062 0.047 -1.006 -5.979 4.817
17.0 5.64645 29.0084 2.710084 Body size Warm 0.007 -0.063 0.077 0.753 -6.076 8.004
-4.0 5.64645 29.0084 2.710084 Fecundity Warm -0.059 -0.170 0.052 -5.715 -15.648 5.345
0.0 5.64645 29.0084 2.710084 Fecundity Warm -0.043 -0.145 0.056 -4.167 -13.472 5.761
20.0 5.64645 29.0084 2.710084 Fecundity Warm 0.039 -0.119 0.197 4.023 -11.244 21.776
0.0 5.64645 29.0084 2.710084 Survival Warm 0.050 -0.317 0.416 5.092 -27.163 51.561
-5.0 5.64645 29.0084 2.710084 Survival Warm 0.038 -0.330 0.409 3.924 -28.111 50.568
17.0 5.64645 29.0084 2.710084 Survival Warm 0.089 -0.302 0.443 9.325 -26.032 55.763

Data visualisation

Marginal means

# Generate predictions at assay_temp_diff = 0, or 5 degrees below or above the control temperatures
emmeans_full_model <- as.data.frame(emmeans(
  lnRR_model_all_moderators,
  specs = ~ assay_temp_diff * select_temp_diff * gen_selection * gen_common_garden | trait_type * warm_cold,
  at = list(assay_temp_diff = c(-5, 0, 5) # Re-acclimated to control, or 5 degrees above/below the control
  ))) 

# Rename variable levels
emmeans_full_model$trait_type <- factor(emmeans_full_model$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_full_model$warm_cold <- factor(emmeans_full_model$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))
emmeans_full_model
##    assay_temp_diff select_temp_diff gen_selection gen_common_garden trait_type
## 1               -5          5.64645       29.0084          2.710084  Body size
## 2                0          5.64645       29.0084          2.710084  Body size
## 3                5          5.64645       29.0084          2.710084  Body size
## 4               -5          5.64645       29.0084          2.710084  Fecundity
## 5                0          5.64645       29.0084          2.710084  Fecundity
## 6                5          5.64645       29.0084          2.710084  Fecundity
## 7               -5          5.64645       29.0084          2.710084   Survival
## 8                0          5.64645       29.0084          2.710084   Survival
## 9                5          5.64645       29.0084          2.710084   Survival
## 10              -5          5.64645       29.0084          2.710084  Body size
## 11               0          5.64645       29.0084          2.710084  Body size
## 12               5          5.64645       29.0084          2.710084  Body size
## 13              -5          5.64645       29.0084          2.710084  Fecundity
## 14               0          5.64645       29.0084          2.710084  Fecundity
## 15               5          5.64645       29.0084          2.710084  Fecundity
## 16              -5          5.64645       29.0084          2.710084   Survival
## 17               0          5.64645       29.0084          2.710084   Survival
## 18               5          5.64645       29.0084          2.710084   Survival
##    warm_cold       emmean   lower.HPD   upper.HPD
## 1       Cold  0.005148823 -0.04970621  0.05952856
## 2       Cold  0.015207363 -0.03269314  0.06623147
## 3       Cold  0.025500722 -0.02830826  0.08255127
## 4       Cold  0.270851221  0.06979423  0.46014868
## 5       Cold -0.044725107 -0.23467509  0.15009005
## 6       Cold -0.359657441 -0.56543988 -0.15530694
## 7       Cold  0.156280791 -0.42491192  0.74822331
## 8       Cold -0.069472920 -0.67875367  0.49053716
## 9       Cold -0.295030787 -0.91381113  0.25757028
## 10      Warm -0.010110065 -0.06165284  0.04704290
## 11      Warm -0.005926964 -0.05257416  0.03948043
## 12      Warm -0.001969011 -0.04986516  0.03975194
## 13      Warm -0.063105837 -0.17796598  0.05170522
## 14      Warm -0.042562540 -0.14470383  0.05601262
## 15      Warm -0.022118434 -0.11624918  0.08314638
## 16      Warm  0.038493731 -0.33004718  0.40924350
## 17      Warm  0.049664228 -0.31694843  0.41581910
## 18      Warm  0.061498001 -0.30913205  0.42179338
# Plot
ggplot() +
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75, 
               lwd=1) +
    geom_quasirandom(data = data,     # Plot effect sizes, scaled by precision
                     aes(x = trait_type:warm_cold, 
                         y = lnRR, 
                         fill = trait_type:warm_cold, 
                         size = 1/sqrt(var_lnRR)), 
                     color = "black",
                     shape = 21,
                     width = 0.3, 
                     alpha = 0.3) +
    geom_errorbar(data = filter(emmeans_full_model,
                                assay_temp_diff == "-5"),  # 5 degrees below control (background)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="white",
                  size = 2.75,
                  width = 0.16,
               position = position_nudge(x=-0.25)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "-5"),  # 5 degrees below control (background)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 21,
               size = 4.5, 
               stroke = 2,
               color="white",
               fill = "white",
               position = position_nudge(x=-0.25)) +
    geom_errorbar(data = filter(emmeans_full_model,
                             assay_temp_diff == "-5"), # 5 degrees below control (credible intervals)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="#06B4BA",
                  size = 2,
                  width = 0.12,
               position = position_nudge(x=-0.25)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "-5"), # 5 degrees below control  (point estimates)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 21,
               size = 3.5, 
               stroke = 2,
               color="#06B4BA",
               fill = "white",
               position = position_nudge(x=-0.25)) +

      geom_errorbar(data = filter(emmeans_full_model,
                                assay_temp_diff == "0"),  # control temperature (background)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="white",
                  size = 2.75,
                  width = 0.16,
               position = position_nudge(x=0)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "0"),  # control temperature (background)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 22,
               size = 4.5, 
               stroke = 2,
               color="white",
               fill = "white",
               position = position_nudge(x=0)) +
    geom_errorbar(data = filter(emmeans_full_model,
                             assay_temp_diff == "0"), # control temperature (credible intervals)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="black",
                  size = 2,
                  width = 0.12,
               position = position_nudge(x=0)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "0"), # control temperature (point estimates)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 22,
               size = 3.5, 
               stroke = 2,
               color="black",
               fill = "white",
               position = position_nudge(x=0)) +
  
      geom_errorbar(data = filter(emmeans_full_model,
                                assay_temp_diff == "5"),  # 5 degrees above control (background)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="white",
                  size = 2.75,
                  width = 0.16,
               position = position_nudge(x=0.25)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "5"),  # 5 degrees above control (background)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 23,
               size = 4.5, 
               stroke = 2,
               color="white",
               fill = "white",
               position = position_nudge(x=0.25)) +
    geom_errorbar(data = filter(emmeans_full_model,
                             assay_temp_diff == "5"), # 5 degrees above control (credible intervals)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="#E80756",
                  size = 2,
                  width = 0.12,
               position = position_nudge(x=0.25)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "5"), # 5 degrees above control (point estimates)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 23,
               size = 3.5, 
               stroke = 2,
               color="#E80756",
               fill = "white",
               position = position_nudge(x=0.25)) +
  
    geom_text(data = sample_sizes,  # Sample size annotations 
              aes(x = trait_type:warm_cold, 
                  y = 1.5,
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1, size = 5, show.legend = FALSE) +
  
    theme_bw() +     # Customize the plot
    labs(y = "lnRR", x = "") +
    scale_size_continuous(range = c(2, 8))+ 
    scale_fill_manual(values = c("#06B4BA", "#E80756", "#06B4BA", "#E80756", "#06B4BA", "#E80756"))+
    scale_color_manual(values = c("Cold" = "#06B4BA", "Warm" = "#E80756")) +  # Text colour
    theme(text = element_text(size = 20, color = "black"),
          legend.title = ggplot2::element_text(size = 16),
          legend.text = ggplot2::element_text(size = 14),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
          panel.border = element_rect(color = "black", size = 1.5)) +
    guides(fill = "none", size = "none")+
    coord_flip() + 
    ylim(-1.5, 1.5)

ggsave(file = "fig/lnRR_all_moderators_marginal_means.png", width = 12, height = 8, dpi = 500)

Overall trend with assay temperature

# Generate predictions for all assay temperatures
emmeans_full_model_assay <- as.data.frame(emmeans(
  lnRR_model_all_moderators,
  specs = ~ assay_temp_diff * select_temp_diff * gen_selection * gen_common_garden | trait_type * warm_cold,
  at = list(assay_temp_diff = seq(min(data$assay_temp_diff), max(data$assay_temp_diff), by = 0.5) # Re-acclimated to control, or 5 degrees above/below the contol
  ))) 

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_assay_temp_diff = min(assay_temp_diff),
    max_assay_temp_diff = max(assay_temp_diff)
  )

# Rename variable levels
emmeans_full_model_assay$trait_type <- factor(emmeans_full_model_assay$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_full_model_assay$warm_cold <- factor(emmeans_full_model_assay$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_full_model_assay <- emmeans_full_model_assay %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    assay_temp_diff >= min_assay_temp_diff,
    assay_temp_diff <= max_assay_temp_diff
  )


# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) +  
    geom_vline(xintercept = 0, # Vertical line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data, # Effect sizes, scaled by precision
                  aes(x = assay_temp_diff, 
                      y = lnRR, 
                      size = 1/sqrt(var_lnRR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_full_model_assay, # Shaded area for credible intervals
                 aes(x = assay_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_full_model_assay,  # Predicted regression line
               aes(y = emmean,
                   x = assay_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) + 
  
    geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  
  facet_wrap(~ trait_type, ncol = 1) + # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Assay temperature difference", y = "lnRR",
       col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3, 3))

ggsave(file = "fig/lnRR_all_moderators_assay_temp_diff.png", width = 12, height = 10, dpi = 500)

Changes in relative trait variance (lnCVR)

Overall model

Model specification

# Model specification
formula <- bf(lnCVR ~ trait_type -1 + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnCVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnCVR_model_overall <- brm(formula, 
                           family = gaussian(),
                           data = data, 
                           data2 = list(phylo_matrix = phylo_matrix,
                                        VCV_lnCVR = VCV_lnCVR),
                           prior = prior,
                           control = list(adapt_delta = 0.99, max_treedepth = 15),
                           iter = 4000, 
                           warmup = 2000,
                           chains = 4, 
                           cores = 4, 
                           seed = 123) 

# Save model
saveRDS(lnCVR_model_overall, file = "RData/lnCVR_model_overall.rds")

Model output

# Load model
lnCVR_model_overall <- readRDS("RData/lnCVR_model_overall.rds")

# Display model output
summary(lnCVR_model_overall)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnCVR ~ trait_type - 1 + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnCVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.11      0.05     0.01     0.22 1.00     1362     2302
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.40      0.04     0.32     0.48 1.00     2165     4001
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.10      0.08     0.00     0.29 1.00     3123     3747
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.06      0.05     0.00
## sd(trait_typefecundity)                          0.14      0.09     0.01
## sd(trait_typesurvival)                           0.48      0.15     0.21
## cor(trait_typebody_size,trait_typefecundity)     0.09      0.49    -0.84
## cor(trait_typebody_size,trait_typesurvival)     -0.03      0.49    -0.88
## cor(trait_typefecundity,trait_typesurvival)     -0.06      0.43    -0.85
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.18 1.00     4025     4524
## sd(trait_typefecundity)                          0.34 1.00     1577     3479
## sd(trait_typesurvival)                           0.81 1.00     3029     3706
## cor(trait_typebody_size,trait_typefecundity)     0.89 1.00     2800     4724
## cor(trait_typebody_size,trait_typesurvival)      0.87 1.00     1260     3139
## cor(trait_typefecundity,trait_typesurvival)      0.76 1.00     2096     3841
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.07      0.05     0.00     0.20 1.00     3402     4336
## 
## Regression Coefficients:
##                     Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## trait_typebody_size     0.04      0.10    -0.14     0.25 1.00     3920     4162
## trait_typefecundity    -0.01      0.10    -0.21     0.19 1.00     4316     4214
## trait_typesurvival      0.13      0.16    -0.19     0.45 1.00     4845     5467
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnCVR_model_overall, summary = TRUE)) %>%
    # Rename categorical variables for cleaner display
rownames_to_column(var = "Parameter") %>%
    mutate(Parameter = gsub("trait_type([a-z_]+)", "\\1", Parameter)) %>%
    # Round numbers to 3 decimal points
mutate(across(c(Estimate, Q2.5, Q97.5), ~round(., 3))) %>%
    select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
    kable() %>%
    kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE) %>%
    row_spec(0, background = "white", color = "black", bold = TRUE) %>%
    kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size 0.045 -0.139 0.250
fecundity -0.013 -0.212 0.192
survival 0.127 -0.185 0.449

Heterogeneity analysis

# Extracting the posterior distribution from the model
posterior <- posterior_samples(lnCVR_model_overall)

# Calculate measurement error variance
sigma2_v <- sum(1/diag(VCV_lnCVR)) * (length(diag(VCV_lnCVR))- 1)/(sum(1/diag(VCV_lnCVR))^2 - sum((1/diag(VCV_lnCVR))^2))

# Calculate the total variance (including the measurement error variance)
var_total <- posterior$sd_experiment_ID__Intercept +
             posterior$sd_obs__Intercept +
             posterior$sd_phylogeny__Intercept +
             posterior$sd_ref__trait_typebody_size +
             posterior$sd_ref__trait_typefecundity +
             posterior$sd_ref__trait_typesurvival +
             posterior$sd_species__Intercept +
             sigma2_v

# Calculate heterogeneity (I2)
I2 <- list(
    I2_total = (var_total - sigma2_v) / var_total, # Total heterogeneity
    I2_study = (posterior$sd_ref__trait_typebody_size + # Heterogeneity explained by study differences
                posterior$sd_ref__trait_typefecundity +
                posterior$sd_ref__trait_typesurvival) / var_total,
    I2_exp = posterior$sd_experiment_ID__Intercept / var_total, # Heterogeneity explained by experiment differences
    I2_sp = posterior$sd_species__Intercept / var_total, # Heterogeneity explained by species differences
    I2_phylo = posterior$sd_phylogeny__Intercept / var_total, # Heterogeneity explained by phylogenetic relatedness
    I2_obs = posterior$sd_obs__Intercept / var_total # Heterogeneity explained by residual variation

)

# Calculate mean and credible intervals 
summary_table <- t(sapply(I2, function(x) {
    c(Mean = 100*round(mean(x),4), 
      ` ` = 100* round(quantile(x, 0.025),4), 
      ` ` = 100*round(quantile(x, 0.975),4))
}))

# Customise table
summary_table <- summary_table %>%
    as.data.frame() %>% 
    rownames_to_column("Variable") %>%
    mutate(
        Variable = recode(Variable,
                          "I2_total"  = "Total",
                          "I2_study"  = "Study",
                          "I2_exp"    = "Experiment",
                          "I2_sp"     = "Species",
                          "I2_phylo"  = "Phylogeny",
                          "I2_obs"    = "Residual")
    ) %>%
    rename(
        lower_HPD = ` .2.5%`,
        upper_HPD = ` .97.5%`
    ) %>%
  mutate(
    Variable = paste0("I<sup>2</sup><sub>", Variable)   # Create a new column with formatted I² and subscripts
  )


# Display table
kable(summary_table, "html", escape = FALSE, 
      col.names = c("Heterogeneity (%)", "Mean", "Lower HPD", "Upper HPD"),
      align = c('l', 'r', 'r', 'r')) %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, width = "200px", bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Heterogeneity (%) Mean Lower HPD Upper HPD
I2Total 90.51 87.57 92.92
I2Study 44.97 29.15 59.30
I2Experiment 7.61 0.72 14.61
I2Species 4.40 0.16 12.65
I2Phylogeny 6.28 0.30 17.32
I2Residual 27.26 18.94 37.61

Data visualisation

# Generate predictions
emmeans_overall <- as.data.frame(emmeans(lnCVR_model_overall, ~ trait_type))

emmeans_overall$trait_type <- factor(emmeans_overall$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))
# Plot
ggplot() +
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75, 
               lwd=1) +
    geom_quasirandom(data = data, # Plot effect sizes, scaled by precision
                     aes(x = trait_type, 
                         y = lnCVR, 
                         size = 1/sqrt(var_lnCVR)), 
                     fill = "gray75",
                     shape = 21,
                     width = 0.25, 
                     alpha = 0.2) +
    geom_errorbar(data = emmeans_overall,   # Plot the point estimates in white for background
                  aes(ymin = lower.HPD, 
                      ymax = upper.HPD,
                      x = trait_type), 
                  size = 2,
                  width = 0.085,
                  color = "white") +
    geom_point(data = emmeans_overall, # Plot the credible intervals in white for background
               aes(x = trait_type, 
                   y = emmean),
               size = 4.5, 
               stroke = 1.5,
               shape = 21,
               color="white",
               fill = "white") +
    geom_errorbar(data = emmeans_overall,  # Plot the point estimates 
                  aes(x = trait_type, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  size = 1.5,
                  width = 0.075,
                  color = "black") +
    geom_point(data = emmeans_overall, # Plot the credible intervals
               aes(x = trait_type, 
                   y = emmean),
               size = 4,
               shape = 21,
               stroke = 1.5,
               color="black",
               fill = "white") +
    geom_text(data = sample_sizes_traits,  # Sample size annotations 
              aes(x = trait_type, 
                  y = 3,
                  label = paste0("k = ", estimates, " (", studies, ")")), 
              hjust = 1, size = 5, show.legend = FALSE) +
    theme_bw() +     # Customize the plot
    labs(y = "lnCVR", x = "") +
    scale_size_continuous(range = c(2, 8))+ 
    theme(text = element_text(size = 20, color = "black"),
          legend.title = ggplot2::element_text(size = 16),
          legend.text = ggplot2::element_text(size = 14),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
          panel.border = element_rect(color = "black", size = 1.5)) +
    guides(color = "none", size = "none")+
    coord_flip() + 
    ylim(-3, 3)

# Save figure
ggsave(file = "fig/lnCVR_overall.png", width = 12, height = 7, dpi = 500)

Temperature regime

Model specification

# Model specification
formula <- bf(lnCVR ~ trait_type:warm_cold -1 + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnCVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnCVR_model_warm_cold <- brm(formula, 
                  family = gaussian(),
                  data = data, 
                  data2 = list(phylo_matrix = phylo_matrix,
                               VCV_lnCVR = VCV_lnCVR),
                  prior = prior,
                  control = list(adapt_delta = 0.99, max_treedepth = 15),
                  iter = 4000, 
                  warmup = 2000,
                  chains = 4, 
                  cores = 4, 
                  seed = 123) 

# Save model
saveRDS(lnCVR_model_warm_cold, file = "RData/lnCVR_model_warm_cold.rds")

Model output

# Load model
lnCVR_model_warm_cold <- readRDS("RData/lnCVR_model_warm_cold.rds")

# Display model output 
summary(lnCVR_model_warm_cold)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnCVR ~ trait_type:warm_cold - 1 + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnCVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.11      0.05     0.01     0.21 1.00     1334     1916
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.40      0.04     0.32     0.49 1.00     2074     4187
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.07     0.00     0.28 1.00     3146     4236
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.06      0.05     0.00
## sd(trait_typefecundity)                          0.13      0.09     0.01
## sd(trait_typesurvival)                           0.49      0.15     0.22
## cor(trait_typebody_size,trait_typefecundity)     0.07      0.49    -0.86
## cor(trait_typebody_size,trait_typesurvival)     -0.00      0.51    -0.89
## cor(trait_typefecundity,trait_typesurvival)     -0.04      0.43    -0.84
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.17 1.00     3651     3866
## sd(trait_typefecundity)                          0.33 1.00     1485     3152
## sd(trait_typesurvival)                           0.81 1.00     3533     4364
## cor(trait_typebody_size,trait_typefecundity)     0.89 1.00     3524     4596
## cor(trait_typebody_size,trait_typesurvival)      0.89 1.00     1148     2616
## cor(trait_typefecundity,trait_typesurvival)      0.79 1.00     2256     3614
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.19 1.00     4014     5084
## 
## Regression Coefficients:
##                                   Estimate Est.Error l-95% CI u-95% CI Rhat
## trait_typebody_size:warm_coldcold    -0.02      0.12    -0.25     0.22 1.00
## trait_typefecundity:warm_coldcold    -0.15      0.20    -0.53     0.23 1.00
## trait_typesurvival:warm_coldcold      0.00      0.27    -0.52     0.53 1.00
## trait_typebody_size:warm_coldwarm     0.06      0.10    -0.13     0.26 1.00
## trait_typefecundity:warm_coldwarm    -0.00      0.10    -0.19     0.20 1.00
## trait_typesurvival:warm_coldwarm      0.14      0.17    -0.19     0.47 1.00
##                                   Bulk_ESS Tail_ESS
## trait_typebody_size:warm_coldcold     3244     3195
## trait_typefecundity:warm_coldcold     4902     4558
## trait_typesurvival:warm_coldcold      5701     5908
## trait_typebody_size:warm_coldwarm     3466     3174
## trait_typefecundity:warm_coldwarm     3853     2660
## trait_typesurvival:warm_coldwarm      5207     4433
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnCVR_model_warm_cold, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>% 
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) -0.020 -0.251 0.216
fecundity(cold) -0.152 -0.529 0.227
survival(cold) 0.001 -0.522 0.533
body_size(warm) 0.057 -0.132 0.259
fecundity(warm) -0.002 -0.194 0.201
survival(warm) 0.141 -0.190 0.471

Contrasts

# Generate predictions
emms <- emmeans(lnCVR_model_warm_cold, specs = ~warm_cold | trait_type)

# Generate contrasts
contrast(emms, method = "pairwise")
## trait_type = body_size:
##  contrast    estimate lower.HPD upper.HPD
##  cold - warm  -0.0779    -0.265     0.114
## 
## trait_type = fecundity:
##  contrast    estimate lower.HPD upper.HPD
##  cold - warm  -0.1509    -0.516     0.228
## 
## trait_type = survival:
##  contrast    estimate lower.HPD upper.HPD
##  cold - warm  -0.1437    -0.667     0.384
## 
## Point estimate displayed: median 
## HPD interval probability: 0.95

Data visualisation

# Generate predictions
emmeans_warm_cold <- as.data.frame(emmeans(lnCVR_model_warm_cold, 
                                           specs = ~ warm_cold | trait_type))

emmeans_warm_cold$trait_type <- factor(emmeans_warm_cold$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))


emmeans_warm_cold$warm_cold <- factor(emmeans_warm_cold$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))
# Plot
ggplot() +
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75, 
               lwd=1) +
    geom_quasirandom(data = data,     # Plot effect sizes, scaled by precision
                     aes(x = trait_type:warm_cold, 
                         y = lnCVR, 
                         fill = trait_type:warm_cold, 
                         size = 1/sqrt(var_lnCVR)), 
                     color = "black",
                     shape = 21,
                     width = 0.25, 
                     alpha = 0.3) +
    geom_errorbar(data = emmeans_warm_cold,  # Plot the point estimates in white for background
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="white",
                  size = 2.5,
                  width = 0.17) +
    geom_point(data = emmeans_warm_cold,  # Plot the credible intervals in white for background
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 21,
               size = 4, 
               stroke = 2,
               color="white",
               fill = "white") +
    geom_errorbar(data = emmeans_warm_cold, # Plot the point estimates 
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="black",
                  size = 2,
                  width = 0.15) +
    geom_point(data = emmeans_warm_cold, # Plot the credible intervals
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 21,
               size = 3.5, 
               stroke = 2,
               color="black",
               fill = "white") +
    geom_text(data = sample_sizes,  # Sample size annotations 
              aes(x = trait_type:warm_cold, 
                  y = 3,
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1, size = 5, show.legend = FALSE) +
    theme_bw() +     # Customize the plot
    labs(y = "lnCVR", x = "") +
    scale_size_continuous(range = c(2, 8))+ 
#    scale_fill_manual(values = c("#A5F820", "#73B706",  "#9CEFFC", "#06A2BA",  "#FED2ED", "#B90674"))+
    scale_fill_manual(values = c("#06B4BA", "#E80756", "#06B4BA", "#E80756", "#06B4BA", "#E80756"))+
    theme(text = element_text(size = 20, color = "black"),
          legend.title = ggplot2::element_text(size = 16),
          legend.text = ggplot2::element_text(size = 14),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
          panel.border = element_rect(color = "black", size = 1.5)) +
    guides(fill = "none", size = "none")+
    coord_flip() + 
    ylim(-3, 3)

ggsave(file = "fig/lnCVR_warm_cold.png", width = 12, height = 7, dpi = 500)

Assay temperature difference

We calculated the difference between the assay temperature and control temperature (assay_temp_diff) to account for the fact that animals were tested to a different range of temperatures. We also predicted that effects will vary if traits are assayed at colder- or warmer-than-control conditions, depending on the temperature regime. Because the variation in assay temperature generates some nuisance heterogeneity (sensu Noble et al., 2017), the results of subsequent models were provided after controlling for assay temperature differences. In order words, the results of all moderators are conditional on assay temperature, meaning that results are interpretable as the difference between control and selected lines, when animals are tested at the control temperature.

Model specification

# Model specification
formula <- bf(lnCVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnCVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnCVR_model_assay_temp_diff <- brm(formula, 
                                  family = gaussian(),
                                  data = data, 
                                  data2 = list(phylo_matrix = phylo_matrix,
                                               VCV_lnCVR = VCV_lnCVR),
                                  prior = prior,
                                  control = list(adapt_delta = 0.99, max_treedepth = 15),
                                  iter = 4000, 
                                  warmup = 2000,
                                  chains = 4, 
                                  cores = 4, 
                                  seed = 123) 

# Save model
saveRDS(lnCVR_model_assay_temp_diff, file = "RData/lnCVR_model_assay_temp_diff.rds")

Model output

# Load model
lnCVR_model_assay_temp_diff <- readRDS("RData/lnCVR_model_assay_temp_diff.rds")

# Display model output
summary(lnCVR_model_assay_temp_diff)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnCVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnCVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.05     0.01     0.20 1.01     1355     3293
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.40      0.04     0.32     0.48 1.00     2181     4146
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.07     0.00     0.28 1.00     3565     4130
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.06      0.05     0.00
## sd(trait_typefecundity)                          0.10      0.08     0.00
## sd(trait_typesurvival)                           0.52      0.15     0.25
## cor(trait_typebody_size,trait_typefecundity)     0.05      0.49    -0.86
## cor(trait_typebody_size,trait_typesurvival)     -0.00      0.50    -0.88
## cor(trait_typefecundity,trait_typesurvival)     -0.05      0.45    -0.85
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.18 1.00     4100     5188
## sd(trait_typefecundity)                          0.30 1.00     2451     3961
## sd(trait_typesurvival)                           0.86 1.00     3645     3396
## cor(trait_typebody_size,trait_typefecundity)     0.88 1.00     5017     5682
## cor(trait_typebody_size,trait_typesurvival)      0.87 1.00     1598     3433
## cor(trait_typefecundity,trait_typesurvival)      0.81 1.00     2117     3653
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.19 1.00     3679     4328
## 
## Regression Coefficients:
##                                                   Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                    -0.02      0.12    -0.24
## trait_typefecundity:warm_coldcold                    -0.28      0.20    -0.67
## trait_typesurvival:warm_coldcold                      0.12      0.29    -0.45
## trait_typebody_size:warm_coldwarm                     0.06      0.11    -0.14
## trait_typefecundity:warm_coldwarm                    -0.06      0.11    -0.26
## trait_typesurvival:warm_coldwarm                      0.24      0.19    -0.13
## trait_typebody_size:warm_coldcold:assay_temp_diff    -0.01      0.02    -0.05
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.14      0.04    -0.22
## trait_typesurvival:warm_coldcold:assay_temp_diff      0.03      0.04    -0.05
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.00      0.02    -0.03
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.02      0.02    -0.01
## trait_typesurvival:warm_coldwarm:assay_temp_diff     -0.03      0.02    -0.07
##                                                   u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                     0.23 1.00     4403
## trait_typefecundity:warm_coldcold                     0.11 1.00     5896
## trait_typesurvival:warm_coldcold                      0.69 1.00     7022
## trait_typebody_size:warm_coldwarm                     0.28 1.00     4306
## trait_typefecundity:warm_coldwarm                     0.16 1.00     5058
## trait_typesurvival:warm_coldwarm                      0.62 1.00     5555
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.03 1.00     4918
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.06 1.00     8871
## trait_typesurvival:warm_coldcold:assay_temp_diff      0.10 1.00     8902
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.04 1.00     6932
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.05 1.00     7381
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.02 1.00     7678
##                                                   Tail_ESS
## trait_typebody_size:warm_coldcold                     4527
## trait_typefecundity:warm_coldcold                     5950
## trait_typesurvival:warm_coldcold                      6292
## trait_typebody_size:warm_coldwarm                     4521
## trait_typefecundity:warm_coldwarm                     4766
## trait_typesurvival:warm_coldwarm                      5541
## trait_typebody_size:warm_coldcold:assay_temp_diff     5124
## trait_typefecundity:warm_coldcold:assay_temp_diff     6069
## trait_typesurvival:warm_coldcold:assay_temp_diff      6487
## trait_typebody_size:warm_coldwarm:assay_temp_diff     6990
## trait_typefecundity:warm_coldwarm:assay_temp_diff     6687
## trait_typesurvival:warm_coldwarm:assay_temp_diff      6171
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnCVR_model_assay_temp_diff, summary = TRUE)) %>%
    # Rename categorical variables for cleaner display
rownames_to_column(var = "Parameter") %>%
    mutate(Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)",
        Parameter), Parameter = gsub("trait_type([a-z_]+)\\(warm\\):assay_temp_diff",
        "\\1(warm): assay_temp_diff", Parameter)) %>%
    # Round numbers to 3 decimal points
mutate(across(c(Estimate, Q2.5, Q97.5), ~round(., 3))) %>%
    select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
    kable() %>%
    kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE) %>%
    row_spec(0, background = "white", color = "black", bold = TRUE) %>%
    kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) -0.017 -0.237 0.230
fecundity(cold) -0.281 -0.667 0.112
survival(cold) 0.118 -0.450 0.694
body_size(warm) 0.055 -0.144 0.277
fecundity(warm) -0.055 -0.259 0.158
survival(warm) 0.235 -0.133 0.619
body_size(cold):assay_temp_diff -0.007 -0.049 0.034
fecundity(cold):assay_temp_diff -0.139 -0.216 -0.063
survival(cold):assay_temp_diff 0.028 -0.048 0.101
body_size(warm):assay_temp_diff 0.002 -0.031 0.036
fecundity(warm):assay_temp_diff 0.018 -0.013 0.048
survival(warm):assay_temp_diff -0.025 -0.074 0.022

Data visualisation

# Generate predictions
emmeans_assay_temp_diff <- as.data.frame(emmeans(
  lnCVR_model_assay_temp_diff,
  specs = ~ assay_temp_diff | trait_type * warm_cold,
  at = list(assay_temp_diff = seq(min(data$assay_temp_diff), max(data$assay_temp_diff), by = 0.5)))
  )

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_assay_temp_diff = min(assay_temp_diff),
    max_assay_temp_diff = max(assay_temp_diff)
  )

emmeans_assay_temp_diff$trait_type <- factor(emmeans_assay_temp_diff$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_assay_temp_diff$warm_cold <- factor(emmeans_assay_temp_diff$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_assay_temp_diff <- emmeans_assay_temp_diff %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    assay_temp_diff >= min_assay_temp_diff,
    assay_temp_diff <= max_assay_temp_diff
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) +  
    geom_vline(xintercept = 0, # Vertical line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data, # Effect sizes, scaled by precision
                  aes(x = assay_temp_diff, 
                      y = lnCVR, 
                      size = 1/sqrt(var_lnCVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_assay_temp_diff, # Shaded area for credible intervals
                 aes(x = assay_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_assay_temp_diff,  # Predicted regression line
               aes(y = emmean,
                   x = assay_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) + 
  
    geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  
  facet_wrap(~ trait_type, ncol = 1) + # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Assay temperature difference", y = "lnCVR",
       col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3, 3))

ggsave(file = "fig/lnCVR_assay_temp_diff.png", width = 12, height = 10, dpi = 500)

Selection temperature

Model specification

# Model specification
formula <- bf(lnCVR ~ 0 + trait_type:warm_cold + 
                          trait_type:warm_cold:assay_temp_diff + 
                          trait_type:warm_cold:select_temp_diff + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnCVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnCVR_model_sel_temp_diff <- brm(formula, 
                                family = gaussian(),
                                data = data, 
                                data2 = list(phylo_matrix = phylo_matrix,
                                             VCV_lnCVR = VCV_lnCVR),
                                prior = prior,
                                control = list(adapt_delta = 0.99, max_treedepth = 15),
                                iter = 4000, 
                                warmup = 2000,
                                chains = 4, 
                                cores = 4, 
                                seed = 123) 

# Save model
saveRDS(lnCVR_model_sel_temp_diff, file = "RData/lnCVR_model_sel_temp_diff.rds")

Model output

# Load model
lnCVR_model_sel_temp_diff <- readRDS("RData/lnCVR_model_sel_temp_diff.rds")

# Display model output
summary(lnCVR_model_sel_temp_diff)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnCVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:select_temp_diff + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnCVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.10      0.06     0.01     0.21 1.00     1120     2464
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.39      0.04     0.32     0.47 1.00     2157     3877
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.08     0.00     0.28 1.00     3736     4900
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.06      0.05     0.00
## sd(trait_typefecundity)                          0.12      0.09     0.00
## sd(trait_typesurvival)                           0.56      0.17     0.27
## cor(trait_typebody_size,trait_typefecundity)     0.01      0.50    -0.87
## cor(trait_typebody_size,trait_typesurvival)     -0.01      0.49    -0.88
## cor(trait_typefecundity,trait_typesurvival)     -0.01      0.44    -0.82
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.19 1.00     4189     4553
## sd(trait_typefecundity)                          0.35 1.00     1509     3322
## sd(trait_typesurvival)                           0.93 1.00     3008     3730
## cor(trait_typebody_size,trait_typefecundity)     0.89 1.00     3113     4820
## cor(trait_typebody_size,trait_typesurvival)      0.86 1.00     1144     2987
## cor(trait_typefecundity,trait_typesurvival)      0.82 1.01     1465     3650
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.19 1.00     3694     4452
## 
## Regression Coefficients:
##                                                    Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                     -0.27      0.25    -0.76
## trait_typefecundity:warm_coldcold                     -0.32      0.54    -1.36
## trait_typesurvival:warm_coldcold                       0.23      1.39    -2.45
## trait_typebody_size:warm_coldwarm                      0.25      0.17    -0.07
## trait_typefecundity:warm_coldwarm                      0.07      0.16    -0.25
## trait_typesurvival:warm_coldwarm                       0.31      0.35    -0.32
## trait_typebody_size:warm_coldcold:assay_temp_diff      0.00      0.02    -0.04
## trait_typefecundity:warm_coldcold:assay_temp_diff     -0.14      0.04    -0.22
## trait_typesurvival:warm_coldcold:assay_temp_diff       0.03      0.04    -0.05
## trait_typebody_size:warm_coldwarm:assay_temp_diff      0.02      0.02    -0.02
## trait_typefecundity:warm_coldwarm:assay_temp_diff      0.02      0.02    -0.01
## trait_typesurvival:warm_coldwarm:assay_temp_diff      -0.02      0.03    -0.07
## trait_typebody_size:warm_coldcold:select_temp_diff     0.04      0.04    -0.03
## trait_typefecundity:warm_coldcold:select_temp_diff     0.01      0.08    -0.15
## trait_typesurvival:warm_coldcold:select_temp_diff     -0.02      0.18    -0.37
## trait_typebody_size:warm_coldwarm:select_temp_diff    -0.05      0.03    -0.10
## trait_typefecundity:warm_coldwarm:select_temp_diff    -0.03      0.03    -0.09
## trait_typesurvival:warm_coldwarm:select_temp_diff     -0.01      0.05    -0.12
##                                                    u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                      0.22 1.00     3662
## trait_typefecundity:warm_coldcold                      0.75 1.00     3726
## trait_typesurvival:warm_coldcold                       2.92 1.00     4993
## trait_typebody_size:warm_coldwarm                      0.58 1.00     4522
## trait_typefecundity:warm_coldwarm                      0.40 1.00     4930
## trait_typesurvival:warm_coldwarm                       1.04 1.00     3935
## trait_typebody_size:warm_coldcold:assay_temp_diff      0.05 1.00     3460
## trait_typefecundity:warm_coldcold:assay_temp_diff     -0.05 1.00     6312
## trait_typesurvival:warm_coldcold:assay_temp_diff       0.10 1.00     7635
## trait_typebody_size:warm_coldwarm:assay_temp_diff      0.05 1.00     4924
## trait_typefecundity:warm_coldwarm:assay_temp_diff      0.06 1.00     6597
## trait_typesurvival:warm_coldwarm:assay_temp_diff       0.03 1.00     7964
## trait_typebody_size:warm_coldcold:select_temp_diff     0.12 1.00     3351
## trait_typefecundity:warm_coldcold:select_temp_diff     0.16 1.00     4122
## trait_typesurvival:warm_coldcold:select_temp_diff      0.35 1.00     4928
## trait_typebody_size:warm_coldwarm:select_temp_diff     0.01 1.00     5247
## trait_typefecundity:warm_coldwarm:select_temp_diff     0.03 1.00     5254
## trait_typesurvival:warm_coldwarm:select_temp_diff      0.08 1.00     4311
##                                                    Tail_ESS
## trait_typebody_size:warm_coldcold                      4684
## trait_typefecundity:warm_coldcold                      4819
## trait_typesurvival:warm_coldcold                       5571
## trait_typebody_size:warm_coldwarm                      4856
## trait_typefecundity:warm_coldwarm                      4858
## trait_typesurvival:warm_coldwarm                       4510
## trait_typebody_size:warm_coldcold:assay_temp_diff      5041
## trait_typefecundity:warm_coldcold:assay_temp_diff      6073
## trait_typesurvival:warm_coldcold:assay_temp_diff       6521
## trait_typebody_size:warm_coldwarm:assay_temp_diff      5938
## trait_typefecundity:warm_coldwarm:assay_temp_diff      6417
## trait_typesurvival:warm_coldwarm:assay_temp_diff       6546
## trait_typebody_size:warm_coldcold:select_temp_diff     4678
## trait_typefecundity:warm_coldcold:select_temp_diff     5201
## trait_typesurvival:warm_coldcold:select_temp_diff      5669
## trait_typebody_size:warm_coldwarm:select_temp_diff     6029
## trait_typefecundity:warm_coldwarm:select_temp_diff     5784
## trait_typesurvival:warm_coldwarm:select_temp_diff      4512
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnCVR_model_sel_temp_diff, summary = TRUE)) %>%
    # Rename categorical variables for cleaner display
rownames_to_column(var = "Parameter") %>%
    mutate(Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)",
        Parameter), Parameter = gsub("trait_type([a-z_]+)\\(warm\\):select_temp_diff",
        "\\1(warm): select_temp_diff", Parameter)) %>%
    # Round numbers to 3 decimal points
mutate(across(c(Estimate, Q2.5, Q97.5), ~round(., 3))) %>%
    select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
    kable() %>%
    kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE) %>%
    row_spec(0, background = "white", color = "black", bold = TRUE) %>%
    kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) -0.273 -0.764 0.221
fecundity(cold) -0.317 -1.363 0.745
survival(cold) 0.229 -2.449 2.924
body_size(warm) 0.247 -0.072 0.576
fecundity(warm) 0.065 -0.253 0.399
survival(warm) 0.315 -0.316 1.036
body_size(cold):assay_temp_diff 0.005 -0.040 0.050
fecundity(cold):assay_temp_diff -0.135 -0.223 -0.050
survival(cold):assay_temp_diff 0.028 -0.050 0.105
body_size(warm):assay_temp_diff 0.017 -0.020 0.055
fecundity(warm):assay_temp_diff 0.024 -0.009 0.055
survival(warm):assay_temp_diff -0.024 -0.073 0.027
body_size(cold):select_temp_diff 0.043 -0.031 0.117
fecundity(cold):select_temp_diff 0.006 -0.146 0.162
survival(cold):select_temp_diff -0.016 -0.374 0.346
body_size(warm):select_temp_diff -0.046 -0.099 0.007
fecundity(warm):select_temp_diff -0.031 -0.094 0.031
survival(warm):select_temp_diff -0.014 -0.120 0.077

Data visualisation

# Generate predictions
emmeans_sel_temp_diff <- as.data.frame(emmeans(
  lnCVR_model_sel_temp_diff,
  specs = ~ select_temp_diff | trait_type * warm_cold,
  at = list(select_temp_diff = seq(min(data$select_temp_diff), max(data$select_temp_diff), by = 0.5),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_select_temp_diff = min(select_temp_diff),
    max_select_temp_diff = max(select_temp_diff)
  )

emmeans_sel_temp_diff$trait_type <- factor(emmeans_sel_temp_diff$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_sel_temp_diff$warm_cold <- factor(emmeans_sel_temp_diff$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_sel_temp_diff <- emmeans_sel_temp_diff %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    select_temp_diff >= min_select_temp_diff,
    select_temp_diff <= max_select_temp_diff
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = select_temp_diff, 
                      y = lnCVR, 
                      size = 1/sqrt(var_lnCVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_sel_temp_diff, # Shaded area for credible intervals
                 aes(x = select_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_sel_temp_diff, # Predicted regression line
               aes(y = emmean,
                   x = select_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Selection temperature difference", y = "lnCVR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3, 3))

ggsave(file = "fig/lnCVR_sel_temp_diff.png", width = 12, height = 7, dpi = 500)

Number of generations of selection

Model specification

# Model specification
formula <- bf(lnCVR ~ 0 + trait_type:warm_cold + 
                          trait_type:warm_cold:assay_temp_diff + 
                          trait_type:warm_cold:scale(gen_selection) + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnCVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnCVR_model_gen_selection <- brm(formula, 
                                family = gaussian(),
                                data = data, 
                                data2 = list(phylo_matrix = phylo_matrix,
                                             VCV_lnCVR = VCV_lnCVR),
                                prior = prior,
                                control = list(adapt_delta = 0.99, max_treedepth = 15),
                                iter = 4000, 
                                warmup = 2000,
                                chains = 4, 
                                cores = 4, 
                                seed = 123) 
# Save model
saveRDS(lnCVR_model_gen_selection, file = "RData/lnCVR_model_gen_selection.rds")

Model output

# Load model
lnCVR_model_gen_selection <- readRDS("RData/lnCVR_model_gen_selection.rds")

# Display model output 
summary(lnCVR_model_gen_selection)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnCVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:scale(gen_selection) + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnCVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.10      0.05     0.01     0.21 1.00     1136     1843
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.40      0.04     0.32     0.48 1.00     1954     4166
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.07     0.00     0.27 1.00     3283     3958
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.06      0.05     0.00
## sd(trait_typefecundity)                          0.10      0.08     0.00
## sd(trait_typesurvival)                           0.57      0.16     0.29
## cor(trait_typebody_size,trait_typefecundity)     0.04      0.50    -0.87
## cor(trait_typebody_size,trait_typesurvival)     -0.02      0.49    -0.87
## cor(trait_typefecundity,trait_typesurvival)     -0.06      0.44    -0.86
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.18 1.00     3623     4379
## sd(trait_typefecundity)                          0.30 1.00     2262     3456
## sd(trait_typesurvival)                           0.93 1.00     2722     3789
## cor(trait_typebody_size,trait_typefecundity)     0.89 1.00     4036     5173
## cor(trait_typebody_size,trait_typesurvival)      0.87 1.00     1132     2745
## cor(trait_typefecundity,trait_typesurvival)      0.79 1.00     1659     2645
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.19 1.00     3793     4342
## 
## Regression Coefficients:
##                                                      Estimate Est.Error
## trait_typebody_size:warm_coldcold                       -0.09      0.13
## trait_typefecundity:warm_coldcold                       -0.38      0.26
## trait_typesurvival:warm_coldcold                         0.15      0.39
## trait_typebody_size:warm_coldwarm                        0.05      0.11
## trait_typefecundity:warm_coldwarm                       -0.10      0.11
## trait_typesurvival:warm_coldwarm                         0.25      0.23
## trait_typebody_size:warm_coldcold:assay_temp_diff       -0.00      0.02
## trait_typefecundity:warm_coldcold:assay_temp_diff       -0.14      0.04
## trait_typesurvival:warm_coldcold:assay_temp_diff         0.03      0.04
## trait_typebody_size:warm_coldwarm:assay_temp_diff        0.00      0.02
## trait_typefecundity:warm_coldwarm:assay_temp_diff        0.02      0.02
## trait_typesurvival:warm_coldwarm:assay_temp_diff        -0.03      0.02
## trait_typebody_size:warm_coldcold:scalegen_selection     0.09      0.09
## trait_typefecundity:warm_coldcold:scalegen_selection     0.04      0.15
## trait_typesurvival:warm_coldcold:scalegen_selection     -0.05      0.24
## trait_typebody_size:warm_coldwarm:scalegen_selection    -0.02      0.06
## trait_typefecundity:warm_coldwarm:scalegen_selection    -0.15      0.10
## trait_typesurvival:warm_coldwarm:scalegen_selection      0.02      0.37
##                                                      l-95% CI u-95% CI Rhat
## trait_typebody_size:warm_coldcold                       -0.33     0.18 1.00
## trait_typefecundity:warm_coldcold                       -0.87     0.14 1.00
## trait_typesurvival:warm_coldcold                        -0.63     0.93 1.00
## trait_typebody_size:warm_coldwarm                       -0.16     0.27 1.00
## trait_typefecundity:warm_coldwarm                       -0.31     0.13 1.00
## trait_typesurvival:warm_coldwarm                        -0.21     0.71 1.00
## trait_typebody_size:warm_coldcold:assay_temp_diff       -0.04     0.04 1.00
## trait_typefecundity:warm_coldcold:assay_temp_diff       -0.22    -0.06 1.00
## trait_typesurvival:warm_coldcold:assay_temp_diff        -0.05     0.10 1.00
## trait_typebody_size:warm_coldwarm:assay_temp_diff       -0.03     0.04 1.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff       -0.01     0.05 1.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff        -0.08     0.02 1.00
## trait_typebody_size:warm_coldcold:scalegen_selection    -0.08     0.26 1.00
## trait_typefecundity:warm_coldcold:scalegen_selection    -0.24     0.33 1.00
## trait_typesurvival:warm_coldcold:scalegen_selection     -0.51     0.42 1.00
## trait_typebody_size:warm_coldwarm:scalegen_selection    -0.14     0.09 1.00
## trait_typefecundity:warm_coldwarm:scalegen_selection    -0.35     0.06 1.00
## trait_typesurvival:warm_coldwarm:scalegen_selection     -0.72     0.74 1.00
##                                                      Bulk_ESS Tail_ESS
## trait_typebody_size:warm_coldcold                        3234     3433
## trait_typefecundity:warm_coldcold                        4321     4665
## trait_typesurvival:warm_coldcold                         3945     4560
## trait_typebody_size:warm_coldwarm                        2958     3218
## trait_typefecundity:warm_coldwarm                        3365     3715
## trait_typesurvival:warm_coldwarm                         3657     4084
## trait_typebody_size:warm_coldcold:assay_temp_diff        3388     4682
## trait_typefecundity:warm_coldcold:assay_temp_diff        6533     6150
## trait_typesurvival:warm_coldcold:assay_temp_diff         5137     5538
## trait_typebody_size:warm_coldwarm:assay_temp_diff        4895     5687
## trait_typefecundity:warm_coldwarm:assay_temp_diff        5555     5630
## trait_typesurvival:warm_coldwarm:assay_temp_diff         6892     5964
## trait_typebody_size:warm_coldcold:scalegen_selection     4020     4607
## trait_typefecundity:warm_coldcold:scalegen_selection     5581     5472
## trait_typesurvival:warm_coldcold:scalegen_selection      5019     5172
## trait_typebody_size:warm_coldwarm:scalegen_selection     5131     5649
## trait_typefecundity:warm_coldwarm:scalegen_selection     4683     4434
## trait_typesurvival:warm_coldwarm:scalegen_selection      4368     5143
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnCVR_model_gen_selection, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((cold|warm)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter),
    # Remove "scale" from gen_selection
    Parameter = gsub("scalegen_selection", "gen_selection", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) -0.089 -0.331 0.181
fecundity(cold) -0.375 -0.869 0.137
survival(cold) 0.153 -0.627 0.926
body_size(warm) 0.050 -0.156 0.271
fecundity(warm) -0.099 -0.315 0.130
survival(warm) 0.247 -0.210 0.711
body_size(cold):assay_temp_diff -0.001 -0.044 0.041
fecundity(cold):assay_temp_diff -0.140 -0.217 -0.064
survival(cold):assay_temp_diff 0.026 -0.052 0.103
body_size(warm):assay_temp_diff 0.003 -0.030 0.036
fecundity(warm):assay_temp_diff 0.021 -0.010 0.053
survival(warm):assay_temp_diff -0.027 -0.075 0.021
body_size(cold):gen_selection 0.092 -0.077 0.259
fecundity(cold):gen_selection 0.045 -0.244 0.326
survival(cold):gen_selection -0.051 -0.509 0.421
body_size(warm):gen_selection -0.024 -0.142 0.094
fecundity(warm):gen_selection -0.145 -0.351 0.057
survival(warm):gen_selection 0.015 -0.720 0.738

Data visualisation

# Generate predictions
emmeans_gen_selection <- as.data.frame(emmeans(
  lnCVR_model_gen_selection,
  specs = ~ gen_selection | trait_type * warm_cold,
  at = list(gen_selection = seq(min(data$gen_selection), max(data$gen_selection), by = 1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0


# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_gen_selection = min(gen_selection),
    max_gen_selection = max(gen_selection)
  )

emmeans_gen_selection$trait_type <- factor(emmeans_gen_selection$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_gen_selection$warm_cold <- factor(emmeans_gen_selection$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_gen_selection <- emmeans_gen_selection %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    gen_selection >= min_gen_selection,
    gen_selection <= max_gen_selection
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = gen_selection, 
                      y = lnCVR, 
                      size = 1/sqrt(var_lnCVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_gen_selection, # Shaded area for credible intervals
                 aes(x = gen_selection,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_gen_selection, # Predicted regression line
               aes(y = emmean,
                   x = gen_selection,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Number of generations of selection", y = "lnCVR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3, 3),
                    xlim = c(0, 150))

ggsave(file = "fig/lnCVR_gen_selection.png", width = 12, height = 7, dpi = 500)

Number of generations of common garden

Model specification

# Model specification
formula <- bf(lnCVR ~ 0 + trait_type:warm_cold + 
                          trait_type:warm_cold:assay_temp_diff + 
                          trait_type:warm_cold:scale(gen_common_garden) + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnCVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnCVR_model_gen_common_garden <- brm(formula, 
                                family = gaussian(),
                                data = data, 
                                data2 = list(phylo_matrix = phylo_matrix,
                                             VCV_lnCVR = VCV_lnCVR),
                                prior = prior,
                                control = list(adapt_delta = 0.99, max_treedepth = 15),
                                iter = 4000, 
                                warmup = 2000,
                                chains = 4, 
                                cores = 4, 
                                seed = 123) 
# Save model
saveRDS(lnCVR_model_gen_common_garden, file = "RData/lnCVR_model_gen_common_garden.rds")

Model output

# Load model
lnCVR_model_gen_common_garden <- readRDS("RData/lnCVR_model_gen_common_garden.rds")

# Display model output 
summary(lnCVR_model_gen_common_garden)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnCVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:scale(gen_common_garden) + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnCVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.05     0.01     0.21 1.00     1293     2743
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.40      0.04     0.33     0.48 1.00     2081     3793
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.10      0.08     0.00     0.29 1.00     2506     3222
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.06      0.05     0.00
## sd(trait_typefecundity)                          0.10      0.08     0.00
## sd(trait_typesurvival)                           0.55      0.16     0.28
## cor(trait_typebody_size,trait_typefecundity)     0.05      0.49    -0.85
## cor(trait_typebody_size,trait_typesurvival)     -0.03      0.49    -0.88
## cor(trait_typefecundity,trait_typesurvival)     -0.04      0.45    -0.84
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.18 1.00     3649     4252
## sd(trait_typefecundity)                          0.31 1.00     1538     2764
## sd(trait_typesurvival)                           0.90 1.00     3047     3663
## cor(trait_typebody_size,trait_typefecundity)     0.89 1.00     3297     5211
## cor(trait_typebody_size,trait_typesurvival)      0.87 1.01      938     2304
## cor(trait_typefecundity,trait_typesurvival)      0.83 1.00     1463     2653
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.19 1.00     2815     3543
## 
## Regression Coefficients:
##                                                          Estimate Est.Error
## trait_typebody_size:warm_coldcold                           -0.01      0.12
## trait_typefecundity:warm_coldcold                           -0.26      0.20
## trait_typesurvival:warm_coldcold                             0.12      0.32
## trait_typebody_size:warm_coldwarm                            0.04      0.11
## trait_typefecundity:warm_coldwarm                           -0.05      0.11
## trait_typesurvival:warm_coldwarm                             0.24      0.20
## trait_typebody_size:warm_coldcold:assay_temp_diff           -0.01      0.02
## trait_typefecundity:warm_coldcold:assay_temp_diff           -0.14      0.04
## trait_typesurvival:warm_coldcold:assay_temp_diff             0.03      0.04
## trait_typebody_size:warm_coldwarm:assay_temp_diff            0.00      0.02
## trait_typefecundity:warm_coldwarm:assay_temp_diff            0.02      0.02
## trait_typesurvival:warm_coldwarm:assay_temp_diff            -0.03      0.02
## trait_typebody_size:warm_coldcold:scalegen_common_garden    -0.04      0.49
## trait_typefecundity:warm_coldcold:scalegen_common_garden     0.29      0.85
## trait_typesurvival:warm_coldcold:scalegen_common_garden      0.02      0.94
## trait_typebody_size:warm_coldwarm:scalegen_common_garden    -0.31      0.39
## trait_typefecundity:warm_coldwarm:scalegen_common_garden    -0.02      0.03
## trait_typesurvival:warm_coldwarm:scalegen_common_garden      0.05      0.81
##                                                          l-95% CI u-95% CI Rhat
## trait_typebody_size:warm_coldcold                           -0.25     0.24 1.00
## trait_typefecundity:warm_coldcold                           -0.65     0.14 1.00
## trait_typesurvival:warm_coldcold                            -0.50     0.76 1.00
## trait_typebody_size:warm_coldwarm                           -0.16     0.26 1.00
## trait_typefecundity:warm_coldwarm                           -0.26     0.17 1.00
## trait_typesurvival:warm_coldwarm                            -0.14     0.63 1.00
## trait_typebody_size:warm_coldcold:assay_temp_diff           -0.05     0.04 1.00
## trait_typefecundity:warm_coldcold:assay_temp_diff           -0.22    -0.06 1.00
## trait_typesurvival:warm_coldcold:assay_temp_diff            -0.05     0.10 1.00
## trait_typebody_size:warm_coldwarm:assay_temp_diff           -0.03     0.04 1.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff           -0.01     0.05 1.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff            -0.08     0.02 1.00
## trait_typebody_size:warm_coldcold:scalegen_common_garden    -1.00     0.92 1.00
## trait_typefecundity:warm_coldcold:scalegen_common_garden    -1.36     2.00 1.00
## trait_typesurvival:warm_coldcold:scalegen_common_garden     -1.79     1.87 1.00
## trait_typebody_size:warm_coldwarm:scalegen_common_garden    -1.08     0.47 1.00
## trait_typefecundity:warm_coldwarm:scalegen_common_garden    -0.08     0.04 1.00
## trait_typesurvival:warm_coldwarm:scalegen_common_garden     -1.61     1.63 1.00
##                                                          Bulk_ESS Tail_ESS
## trait_typebody_size:warm_coldcold                            2851     3100
## trait_typefecundity:warm_coldcold                            4004     4578
## trait_typesurvival:warm_coldcold                             4694     5317
## trait_typebody_size:warm_coldwarm                            3202     3464
## trait_typefecundity:warm_coldwarm                            3433     3948
## trait_typesurvival:warm_coldwarm                             3213     4539
## trait_typebody_size:warm_coldcold:assay_temp_diff            3002     4645
## trait_typefecundity:warm_coldcold:assay_temp_diff            5549     6001
## trait_typesurvival:warm_coldcold:assay_temp_diff             5136     6370
## trait_typebody_size:warm_coldwarm:assay_temp_diff            4927     6156
## trait_typefecundity:warm_coldwarm:assay_temp_diff            4678     5338
## trait_typesurvival:warm_coldwarm:assay_temp_diff             5295     5614
## trait_typebody_size:warm_coldcold:scalegen_common_garden     5230     5565
## trait_typefecundity:warm_coldcold:scalegen_common_garden     6984     5478
## trait_typesurvival:warm_coldcold:scalegen_common_garden      4118     5376
## trait_typebody_size:warm_coldwarm:scalegen_common_garden     5169     5857
## trait_typefecundity:warm_coldwarm:scalegen_common_garden     6263     6362
## trait_typesurvival:warm_coldwarm:scalegen_common_garden      4182     4925
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnCVR_model_gen_common_garden, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((cold|warm)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter),
    # Remove "scale" from gen_common_garden
    Parameter = gsub("scalegen_common_garden", "gen_common_garden", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) -0.014 -0.245 0.242
fecundity(cold) -0.260 -0.648 0.145
survival(cold) 0.124 -0.500 0.759
body_size(warm) 0.043 -0.162 0.265
fecundity(warm) -0.048 -0.256 0.165
survival(warm) 0.244 -0.138 0.634
body_size(cold):assay_temp_diff -0.008 -0.049 0.035
fecundity(cold):assay_temp_diff -0.141 -0.218 -0.063
survival(cold):assay_temp_diff 0.027 -0.048 0.104
body_size(warm):assay_temp_diff 0.001 -0.032 0.036
fecundity(warm):assay_temp_diff 0.018 -0.014 0.049
survival(warm):assay_temp_diff -0.026 -0.075 0.023
body_size(cold):gen_common_garden -0.041 -1.000 0.917
fecundity(cold):gen_common_garden 0.290 -1.362 2.000
survival(cold):gen_common_garden 0.021 -1.795 1.866
body_size(warm):gen_common_garden -0.314 -1.079 0.466
fecundity(warm):gen_common_garden -0.022 -0.079 0.035
survival(warm):gen_common_garden 0.046 -1.608 1.627

Data visualisation

# Generate predictions
emmeans_gen_common_garden <- as.data.frame(emmeans(
  lnCVR_model_gen_common_garden,
  specs = ~ gen_common_garden | trait_type * warm_cold,
  at = list(gen_common_garden = seq(min(data$gen_common_garden), max(data$gen_common_garden), by = 1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_gen_common_garden = min(gen_common_garden),
    max_gen_common_garden = max(gen_common_garden)
  )

emmeans_gen_common_garden$trait_type <- factor(emmeans_gen_common_garden$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_gen_common_garden$warm_cold <- factor(emmeans_gen_common_garden$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_gen_common_garden <- emmeans_gen_common_garden %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    gen_common_garden >= min_gen_common_garden,
    gen_common_garden <= max_gen_common_garden
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = gen_common_garden, 
                      y = lnCVR, 
                      size = 1/sqrt(var_lnCVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_gen_common_garden, # Shaded area for credible intervals
                 aes(x = gen_common_garden,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_gen_common_garden, # Predicted regression line
               aes(y = emmean,
                   x = gen_common_garden,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Number of generations of common garden", y = "lnCVR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3, 3),
                    xlim = c(0, 12))

ggsave(file = "fig/lnCVR_gen_common_garden.png", width = 12, height = 7, dpi = 500)

Population size

Model specification

# Model specification
formula <- bf(lnCVR ~ 0 + trait_type:warm_cold + 
                          trait_type:warm_cold:assay_temp_diff + 
                          trait_type:warm_cold:scale(pop_size) + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnCVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnCVR_model_pop_size <- brm(formula, 
                                family = gaussian(),
                                data = data, 
                                data2 = list(phylo_matrix = phylo_matrix,
                                             VCV_lnCVR = VCV_lnCVR),
                                prior = prior,
                                control = list(adapt_delta = 0.99, max_treedepth = 15),
                                iter = 4000, 
                                warmup = 2000,
                                chains = 4, 
                                cores = 4, 
                                seed = 123) 
# Save model
saveRDS(lnCVR_model_pop_size, file = "RData/lnCVR_model_pop_size.rds")

Model output

# Load model
lnCVR_model_pop_size <- readRDS("RData/lnCVR_model_pop_size.rds")

# Display model output 
summary(lnCVR_model_pop_size)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnCVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:scale(pop_size) + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnCVR) 
##    Data: data (Number of observations: 426) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 79) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.08      0.05     0.00     0.19 1.00     1928     3870
## 
## ~obs (Number of levels: 426) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.26      0.03     0.20     0.32 1.00     3563     4726
## 
## ~phylogeny (Number of levels: 22) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.08     0.00     0.28 1.00     3836     5030
## 
## ~ref (Number of levels: 41) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.07      0.06     0.00
## sd(trait_typefecundity)                          0.17      0.10     0.01
## sd(trait_typesurvival)                           0.31      0.13     0.06
## cor(trait_typebody_size,trait_typefecundity)    -0.01      0.48    -0.86
## cor(trait_typebody_size,trait_typesurvival)     -0.07      0.48    -0.88
## cor(trait_typefecundity,trait_typesurvival)      0.09      0.48    -0.82
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.21 1.00     3844     4628
## sd(trait_typefecundity)                          0.40 1.00     1859     3255
## sd(trait_typesurvival)                           0.59 1.00     2879     1949
## cor(trait_typebody_size,trait_typefecundity)     0.87 1.00     3526     5348
## cor(trait_typebody_size,trait_typesurvival)      0.84 1.00     2377     4567
## cor(trait_typefecundity,trait_typesurvival)      0.90 1.00     3260     5476
## 
## ~species (Number of levels: 22) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.07      0.06     0.00     0.22 1.00     3810     5167
## 
## Regression Coefficients:
##                                                   Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                     0.02      0.12    -0.21
## trait_typefecundity:warm_coldcold                    -0.12      0.20    -0.50
## trait_typesurvival:warm_coldcold                      0.05      0.25    -0.44
## trait_typebody_size:warm_coldwarm                    -0.01      0.10    -0.21
## trait_typefecundity:warm_coldwarm                     0.00      0.11    -0.22
## trait_typesurvival:warm_coldwarm                      0.01      0.15    -0.28
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.01      0.02    -0.03
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.12      0.04    -0.19
## trait_typesurvival:warm_coldcold:assay_temp_diff      0.03      0.03    -0.04
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.01      0.02    -0.02
## trait_typefecundity:warm_coldwarm:assay_temp_diff    -0.01      0.02    -0.04
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.00      0.02    -0.04
## trait_typebody_size:warm_coldcold:scalepop_size      -0.12      0.07    -0.27
## trait_typefecundity:warm_coldcold:scalepop_size      -0.17      0.16    -0.47
## trait_typesurvival:warm_coldcold:scalepop_size       -0.06      0.24    -0.53
## trait_typebody_size:warm_coldwarm:scalepop_size      -0.01      0.05    -0.10
## trait_typefecundity:warm_coldwarm:scalepop_size      -0.07      0.07    -0.22
## trait_typesurvival:warm_coldwarm:scalepop_size       -0.09      0.11    -0.30
##                                                   u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                     0.26 1.00     4233
## trait_typefecundity:warm_coldcold                     0.28 1.00     6196
## trait_typesurvival:warm_coldcold                      0.54 1.00     6169
## trait_typebody_size:warm_coldwarm                     0.20 1.00     4049
## trait_typefecundity:warm_coldwarm                     0.22 1.00     4479
## trait_typesurvival:warm_coldwarm                      0.31 1.00     5233
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.04 1.00     5531
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.05 1.00     7889
## trait_typesurvival:warm_coldcold:assay_temp_diff      0.09 1.00     9465
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.04 1.00     7338
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.02 1.00     9093
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.04 1.00     9999
## trait_typebody_size:warm_coldcold:scalepop_size       0.03 1.00     4773
## trait_typefecundity:warm_coldcold:scalepop_size       0.16 1.00     5944
## trait_typesurvival:warm_coldcold:scalepop_size        0.42 1.00     8192
## trait_typebody_size:warm_coldwarm:scalepop_size       0.09 1.00     7127
## trait_typefecundity:warm_coldwarm:scalepop_size       0.07 1.00     6452
## trait_typesurvival:warm_coldwarm:scalepop_size        0.14 1.00     6860
##                                                   Tail_ESS
## trait_typebody_size:warm_coldcold                     4549
## trait_typefecundity:warm_coldcold                     5844
## trait_typesurvival:warm_coldcold                      6334
## trait_typebody_size:warm_coldwarm                     4031
## trait_typefecundity:warm_coldwarm                     4427
## trait_typesurvival:warm_coldwarm                      4876
## trait_typebody_size:warm_coldcold:assay_temp_diff     5718
## trait_typefecundity:warm_coldcold:assay_temp_diff     6041
## trait_typesurvival:warm_coldcold:assay_temp_diff      6331
## trait_typebody_size:warm_coldwarm:assay_temp_diff     6816
## trait_typefecundity:warm_coldwarm:assay_temp_diff     6546
## trait_typesurvival:warm_coldwarm:assay_temp_diff      6555
## trait_typebody_size:warm_coldcold:scalepop_size       5270
## trait_typefecundity:warm_coldcold:scalepop_size       5760
## trait_typesurvival:warm_coldcold:scalepop_size        6860
## trait_typebody_size:warm_coldwarm:scalepop_size       6336
## trait_typefecundity:warm_coldwarm:scalepop_size       5785
## trait_typesurvival:warm_coldwarm:scalepop_size        5831
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnCVR_model_pop_size, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((cold|warm)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter),
    # Remove "scale" from pop_size
    Parameter = gsub("scalepop_size", "pop_size", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) 0.018 -0.211 0.256
fecundity(cold) -0.116 -0.503 0.278
survival(cold) 0.050 -0.439 0.543
body_size(warm) -0.007 -0.211 0.201
fecundity(warm) 0.003 -0.219 0.220
survival(warm) 0.011 -0.282 0.315
body_size(cold):assay_temp_diff 0.007 -0.028 0.043
fecundity(cold):assay_temp_diff -0.119 -0.191 -0.048
survival(cold):assay_temp_diff 0.028 -0.038 0.094
body_size(warm):assay_temp_diff 0.008 -0.021 0.037
fecundity(warm):assay_temp_diff -0.011 -0.041 0.020
survival(warm):assay_temp_diff 0.001 -0.042 0.042
body_size(cold):pop_size -0.119 -0.267 0.026
fecundity(cold):pop_size -0.166 -0.472 0.160
survival(cold):pop_size -0.055 -0.527 0.417
body_size(warm):pop_size -0.005 -0.102 0.092
fecundity(warm):pop_size -0.072 -0.217 0.069
survival(warm):pop_size -0.086 -0.301 0.137

Data visualisation

# Generate predictions
emmeans_pop_size <- as.data.frame(emmeans(
  lnCVR_model_pop_size,
  specs = ~ pop_size | trait_type * warm_cold,
  at = list(pop_size = seq(min(data$pop_size, na.rm=T), max(data$pop_size, na.rm=T), by = 50),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_pop_size = min(pop_size, na.rm=T),
    max_pop_size = max(pop_size, na.rm=T)
  )

emmeans_pop_size$trait_type <- factor(emmeans_pop_size$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_pop_size$warm_cold <- factor(emmeans_pop_size$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_pop_size <- emmeans_pop_size %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    pop_size >= min_pop_size,
    pop_size <= max_pop_size
  )

# Calculate sample sizes and study counts for population size
sample_sizes_pop_size <- data %>%
  filter(is.na(pop_size)==FALSE) %>% 
  group_by(trait_type, warm_cold) %>%
  summarise(
    estimates = n(),
    studies = n_distinct(ref)
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = pop_size, 
                      y = lnCVR, 
                      size = 1/sqrt(var_lnCVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_pop_size, # Shaded area for credible intervals
                 aes(x = pop_size,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_pop_size, # Predicted regression line
               aes(y = emmean,
                   x = pop_size,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes_pop_size, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Population size", y = "lnCVR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3, 3))

ggsave(file = "fig/lnCVR_pop_size.png", width = 12, height = 7, dpi = 500)

All moderators

Model specification

# Model specification
formula <- bf(lnCVR ~ 0 + trait_type:warm_cold + 
                trait_type:warm_cold:assay_temp_diff + 
                trait_type:warm_cold:scale(select_temp_diff) +
                trait_type:warm_cold:scale(gen_selection) + 
                trait_type:warm_cold:scale(gen_common_garden) + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnCVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnCVR_model_all_moderators <- brm(formula, 
                                  family = gaussian(),
                                  data = data, 
                                  data2 = list(phylo_matrix = phylo_matrix,
                                               VCV_lnCVR = VCV_lnCVR),
                                  prior = prior,
                                  control = list(adapt_delta = 0.99, max_treedepth = 15),
                                  iter = 4000, 
                                  warmup = 2000,
                                  chains = 4, 
                                  cores = 4, 
                                  seed = 123) 

# Save model
saveRDS(lnCVR_model_all_moderators, file = "RData/lnCVR_model_all_moderators.rds")

Model output

# Load model
lnCVR_model_all_moderators <- readRDS("RData/lnCVR_model_all_moderators.rds")

# Display model output 
summary(lnCVR_model_all_moderators)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnCVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:scale(select_temp_diff) + trait_type:warm_cold:scale(gen_selection) + trait_type:warm_cold:scale(gen_common_garden) + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnCVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.10      0.06     0.01     0.22 1.00     1377     3121
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.40      0.04     0.32     0.48 1.00     2187     4271
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.10      0.08     0.00     0.29 1.00     4220     4874
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.07      0.05     0.00
## sd(trait_typefecundity)                          0.12      0.10     0.00
## sd(trait_typesurvival)                           0.67      0.20     0.34
## cor(trait_typebody_size,trait_typefecundity)     0.01      0.50    -0.88
## cor(trait_typebody_size,trait_typesurvival)     -0.01      0.50    -0.88
## cor(trait_typefecundity,trait_typesurvival)     -0.01      0.45    -0.84
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.20 1.00     4609     4688
## sd(trait_typefecundity)                          0.36 1.00     1890     3738
## sd(trait_typesurvival)                           1.12 1.00     2811     4651
## cor(trait_typebody_size,trait_typefecundity)     0.87 1.00     4835     5800
## cor(trait_typebody_size,trait_typesurvival)      0.88 1.00     1376     3874
## cor(trait_typefecundity,trait_typesurvival)      0.83 1.00     1920     3925
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.19 1.00     4809     5078
## 
## Regression Coefficients:
##                                                          Estimate Est.Error
## trait_typebody_size:warm_coldcold                           -0.09      0.13
## trait_typefecundity:warm_coldcold                           -0.40      0.27
## trait_typesurvival:warm_coldcold                             0.22      0.57
## trait_typebody_size:warm_coldwarm                           -0.02      0.11
## trait_typefecundity:warm_coldwarm                           -0.12      0.12
## trait_typesurvival:warm_coldwarm                             0.26      0.28
## trait_typebody_size:warm_coldcold:assay_temp_diff            0.01      0.02
## trait_typefecundity:warm_coldcold:assay_temp_diff           -0.14      0.05
## trait_typesurvival:warm_coldcold:assay_temp_diff             0.03      0.04
## trait_typebody_size:warm_coldwarm:assay_temp_diff            0.02      0.02
## trait_typefecundity:warm_coldwarm:assay_temp_diff            0.02      0.02
## trait_typesurvival:warm_coldwarm:assay_temp_diff            -0.03      0.03
## trait_typebody_size:warm_coldcold:scaleselect_temp_diff      0.10      0.13
## trait_typefecundity:warm_coldcold:scaleselect_temp_diff      0.00      0.26
## trait_typesurvival:warm_coldcold:scaleselect_temp_diff       0.12      1.09
## trait_typebody_size:warm_coldwarm:scaleselect_temp_diff     -0.15      0.09
## trait_typefecundity:warm_coldwarm:scaleselect_temp_diff     -0.06      0.11
## trait_typesurvival:warm_coldwarm:scaleselect_temp_diff      -0.09      0.19
## trait_typebody_size:warm_coldcold:scalegen_selection         0.07      0.10
## trait_typefecundity:warm_coldcold:scalegen_selection         0.09      0.17
## trait_typesurvival:warm_coldcold:scalegen_selection         -0.13      0.48
## trait_typebody_size:warm_coldwarm:scalegen_selection        -0.04      0.06
## trait_typefecundity:warm_coldwarm:scalegen_selection        -0.12      0.12
## trait_typesurvival:warm_coldwarm:scalegen_selection          0.05      0.47
## trait_typebody_size:warm_coldcold:scalegen_common_garden    -0.06      0.55
## trait_typefecundity:warm_coldcold:scalegen_common_garden     0.51      0.97
## trait_typesurvival:warm_coldcold:scalegen_common_garden     -0.33      1.56
## trait_typebody_size:warm_coldwarm:scalegen_common_garden    -0.24      0.40
## trait_typefecundity:warm_coldwarm:scalegen_common_garden    -0.01      0.03
## trait_typesurvival:warm_coldwarm:scalegen_common_garden      0.04      0.95
##                                                          l-95% CI u-95% CI Rhat
## trait_typebody_size:warm_coldcold                           -0.34     0.18 1.00
## trait_typefecundity:warm_coldcold                           -0.93     0.14 1.00
## trait_typesurvival:warm_coldcold                            -0.92     1.35 1.00
## trait_typebody_size:warm_coldwarm                           -0.24     0.21 1.00
## trait_typefecundity:warm_coldwarm                           -0.36     0.13 1.00
## trait_typesurvival:warm_coldwarm                            -0.28     0.81 1.00
## trait_typebody_size:warm_coldcold:assay_temp_diff           -0.04     0.05 1.00
## trait_typefecundity:warm_coldcold:assay_temp_diff           -0.23    -0.05 1.00
## trait_typesurvival:warm_coldcold:assay_temp_diff            -0.05     0.11 1.00
## trait_typebody_size:warm_coldwarm:assay_temp_diff           -0.02     0.05 1.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff           -0.01     0.06 1.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff            -0.08     0.03 1.00
## trait_typebody_size:warm_coldcold:scaleselect_temp_diff     -0.15     0.37 1.00
## trait_typefecundity:warm_coldcold:scaleselect_temp_diff     -0.51     0.51 1.00
## trait_typesurvival:warm_coldcold:scaleselect_temp_diff      -2.07     2.26 1.00
## trait_typebody_size:warm_coldwarm:scaleselect_temp_diff     -0.32     0.03 1.00
## trait_typefecundity:warm_coldwarm:scaleselect_temp_diff     -0.28     0.15 1.00
## trait_typesurvival:warm_coldwarm:scaleselect_temp_diff      -0.48     0.26 1.00
## trait_typebody_size:warm_coldcold:scalegen_selection        -0.13     0.27 1.00
## trait_typefecundity:warm_coldcold:scalegen_selection        -0.26     0.42 1.00
## trait_typesurvival:warm_coldcold:scalegen_selection         -1.07     0.82 1.00
## trait_typebody_size:warm_coldwarm:scalegen_selection        -0.16     0.08 1.00
## trait_typefecundity:warm_coldwarm:scalegen_selection        -0.36     0.12 1.00
## trait_typesurvival:warm_coldwarm:scalegen_selection         -0.90     0.97 1.00
## trait_typebody_size:warm_coldcold:scalegen_common_garden    -1.15     1.00 1.00
## trait_typefecundity:warm_coldcold:scalegen_common_garden    -1.40     2.43 1.00
## trait_typesurvival:warm_coldcold:scalegen_common_garden     -3.43     2.65 1.00
## trait_typebody_size:warm_coldwarm:scalegen_common_garden    -1.02     0.56 1.00
## trait_typefecundity:warm_coldwarm:scalegen_common_garden    -0.07     0.05 1.00
## trait_typesurvival:warm_coldwarm:scalegen_common_garden     -1.82     1.91 1.00
##                                                          Bulk_ESS Tail_ESS
## trait_typebody_size:warm_coldcold                            5633     5252
## trait_typefecundity:warm_coldcold                            6562     6145
## trait_typesurvival:warm_coldcold                             6185     5366
## trait_typebody_size:warm_coldwarm                            4994     5280
## trait_typefecundity:warm_coldwarm                            5866     5615
## trait_typesurvival:warm_coldwarm                             5065     5349
## trait_typebody_size:warm_coldcold:assay_temp_diff            4449     6250
## trait_typefecundity:warm_coldcold:assay_temp_diff            9299     6722
## trait_typesurvival:warm_coldcold:assay_temp_diff             9106     6383
## trait_typebody_size:warm_coldwarm:assay_temp_diff            6480     6607
## trait_typefecundity:warm_coldwarm:assay_temp_diff            7267     6527
## trait_typesurvival:warm_coldwarm:assay_temp_diff            10561     6446
## trait_typebody_size:warm_coldcold:scaleselect_temp_diff      7028     6159
## trait_typefecundity:warm_coldcold:scaleselect_temp_diff      7620     6412
## trait_typesurvival:warm_coldcold:scaleselect_temp_diff       5130     4539
## trait_typebody_size:warm_coldwarm:scaleselect_temp_diff      8813     7237
## trait_typefecundity:warm_coldwarm:scaleselect_temp_diff      6749     5735
## trait_typesurvival:warm_coldwarm:scaleselect_temp_diff       6028     5134
## trait_typebody_size:warm_coldcold:scalegen_selection         6995     6454
## trait_typefecundity:warm_coldcold:scalegen_selection         8805     6229
## trait_typesurvival:warm_coldcold:scalegen_selection          5874     5486
## trait_typebody_size:warm_coldwarm:scalegen_selection         8712     6476
## trait_typefecundity:warm_coldwarm:scalegen_selection         7044     5964
## trait_typesurvival:warm_coldwarm:scalegen_selection          5684     4810
## trait_typebody_size:warm_coldcold:scalegen_common_garden    10553     7087
## trait_typefecundity:warm_coldcold:scalegen_common_garden    10086     6398
## trait_typesurvival:warm_coldcold:scalegen_common_garden      5725     5479
## trait_typebody_size:warm_coldwarm:scalegen_common_garden     9508     6315
## trait_typefecundity:warm_coldwarm:scalegen_common_garden     9450     6865
## trait_typesurvival:warm_coldwarm:scalegen_common_garden      8083     6912
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnCVR_model_all_moderators, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((cold|warm)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter),
    # Remove "scale" from all moderator variables
    Parameter = gsub("scale", "", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) -0.090 -0.344 0.182
fecundity(cold) -0.399 -0.930 0.142
survival(cold) 0.223 -0.918 1.350
body_size(warm) -0.017 -0.243 0.214
fecundity(warm) -0.119 -0.364 0.133
survival(warm) 0.265 -0.278 0.813
body_size(cold):assay_temp_diff 0.006 -0.038 0.053
fecundity(cold):assay_temp_diff -0.138 -0.226 -0.051
survival(cold):assay_temp_diff 0.030 -0.050 0.110
body_size(warm):assay_temp_diff 0.015 -0.022 0.054
fecundity(warm):assay_temp_diff 0.024 -0.009 0.057
survival(warm):assay_temp_diff -0.025 -0.076 0.026
body_size(cold):select_temp_diff 0.102 -0.153 0.370
fecundity(cold):select_temp_diff 0.004 -0.506 0.511
survival(cold):select_temp_diff 0.117 -2.070 2.265
body_size(warm):select_temp_diff -0.149 -0.325 0.027
fecundity(warm):select_temp_diff -0.060 -0.278 0.147
survival(warm):select_temp_diff -0.085 -0.481 0.261
body_size(cold):gen_selection 0.069 -0.126 0.269
fecundity(cold):gen_selection 0.088 -0.258 0.420
survival(cold):gen_selection -0.130 -1.072 0.824
body_size(warm):gen_selection -0.042 -0.164 0.079
fecundity(warm):gen_selection -0.122 -0.359 0.118
survival(warm):gen_selection 0.047 -0.898 0.971
body_size(cold):gen_common_garden -0.063 -1.147 0.997
fecundity(cold):gen_common_garden 0.508 -1.400 2.428
survival(cold):gen_common_garden -0.334 -3.426 2.647
body_size(warm):gen_common_garden -0.236 -1.020 0.562
fecundity(warm):gen_common_garden -0.011 -0.073 0.051
survival(warm):gen_common_garden 0.038 -1.822 1.914
# Generate predicted values at different assay temperatures
emmeans_full_model <- as.data.frame(emmeans(
  lnCVR_model_all_moderators,
  specs = ~ assay_temp_diff * select_temp_diff * gen_selection * gen_common_garden | trait_type * warm_cold,
  at = list(assay_temp_diff = c(-8.5, -4, 0, 4, 5, -5, 17, 20)) # Predict at unique min, control, max values
))

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_assay = min(assay_temp_diff),
    max_assay = max(assay_temp_diff),
    control_assay = 0
  )

emmeans_full_model$trait_type <- factor(emmeans_full_model$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_full_model$warm_cold <- factor(emmeans_full_model$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_full_model %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    assay_temp_diff == min_assay |
    assay_temp_diff == max_assay |
    assay_temp_diff == control_assay) %>% 
    dplyr::select(-min_assay, -max_assay, -control_assay) %>% 
    mutate(percentage_change = (exp(emmean) - 1) * 100,
           percentage_lower_HPD = (exp(lower.HPD) - 1) * 100,
           percentage_upper_HPD = (exp(upper.HPD) - 1) * 100) %>%
  mutate(across(c(emmean, 
                  lower.HPD, 
                  upper.HPD, 
                  percentage_change,
                  percentage_lower_HPD, 
                  percentage_upper_HPD), ~ round(., 3))) %>%   # Round numbers to 3 decimal points
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
assay_temp_diff select_temp_diff gen_selection gen_common_garden trait_type warm_cold emmean lower.HPD upper.HPD percentage_change percentage_lower_HPD percentage_upper_HPD
-8.5 5.64645 29.0084 2.710084 Body size Cold -0.140 -0.594 0.329 -13.104 -44.796 38.892
0.0 5.64645 29.0084 2.710084 Body size Cold -0.092 -0.349 0.172 -8.758 -29.473 18.818
5.0 5.64645 29.0084 2.710084 Body size Cold -0.062 -0.417 0.278 -6.047 -34.070 31.988
-8.5 5.64645 29.0084 2.710084 Fecundity Cold 0.767 -0.165 1.688 115.263 -15.191 440.604
0.0 5.64645 29.0084 2.710084 Fecundity Cold -0.400 -0.941 0.125 -32.991 -60.993 13.367
5.0 5.64645 29.0084 2.710084 Fecundity Cold -1.090 -1.785 -0.435 -66.371 -83.222 -35.277
-8.5 5.64645 29.0084 2.710084 Survival Cold -0.036 -1.311 1.247 -3.495 -73.041 248.077
0.0 5.64645 29.0084 2.710084 Survival Cold 0.222 -0.910 1.353 24.911 -59.739 286.737
4.0 5.64645 29.0084 2.710084 Survival Cold 0.344 -0.824 1.561 40.996 -56.111 376.140
0.0 5.64645 29.0084 2.710084 Body size Warm -0.019 -0.245 0.211 -1.860 -21.713 23.475
-5.0 5.64645 29.0084 2.710084 Body size Warm -0.092 -0.450 0.243 -8.819 -36.239 27.506
17.0 5.64645 29.0084 2.710084 Body size Warm 0.235 -0.342 0.815 26.499 -28.962 125.950
-4.0 5.64645 29.0084 2.710084 Fecundity Warm -0.215 -0.545 0.117 -19.318 -42.019 12.451
0.0 5.64645 29.0084 2.710084 Fecundity Warm -0.122 -0.369 0.126 -11.486 -30.832 13.427
20.0 5.64645 29.0084 2.710084 Fecundity Warm 0.357 -0.227 0.938 42.928 -20.273 155.540
0.0 5.64645 29.0084 2.710084 Survival Warm 0.260 -0.297 0.790 29.726 -25.718 120.370
-5.0 5.64645 29.0084 2.710084 Survival Warm 0.385 -0.268 1.036 46.921 -23.532 181.703
17.0 5.64645 29.0084 2.710084 Survival Warm -0.160 -1.057 0.798 -14.760 -65.256 122.177

Data visualisation

Marginal means

# Generate predictions at assay_temp_diff = 0, or 5 degrees below or above the control temperatures
emmeans_full_model <- as.data.frame(emmeans(
  lnCVR_model_all_moderators,
  specs = ~ assay_temp_diff * select_temp_diff * gen_selection * gen_common_garden | trait_type * warm_cold,
  at = list(assay_temp_diff = c(-5, 0, 5) # Re-acclimated to control, or 5 degrees above/below the contol
  ))) 

# Rename variable levels
emmeans_full_model$trait_type <- factor(emmeans_full_model$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_full_model$warm_cold <- factor(emmeans_full_model$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))
emmeans_full_model
##    assay_temp_diff select_temp_diff gen_selection gen_common_garden trait_type
## 1               -5          5.64645       29.0084          2.710084  Body size
## 2                0          5.64645       29.0084          2.710084  Body size
## 3                5          5.64645       29.0084          2.710084  Body size
## 4               -5          5.64645       29.0084          2.710084  Fecundity
## 5                0          5.64645       29.0084          2.710084  Fecundity
## 6                5          5.64645       29.0084          2.710084  Fecundity
## 7               -5          5.64645       29.0084          2.710084   Survival
## 8                0          5.64645       29.0084          2.710084   Survival
## 9                5          5.64645       29.0084          2.710084   Survival
## 10              -5          5.64645       29.0084          2.710084  Body size
## 11               0          5.64645       29.0084          2.710084  Body size
## 12               5          5.64645       29.0084          2.710084  Body size
## 13              -5          5.64645       29.0084          2.710084  Fecundity
## 14               0          5.64645       29.0084          2.710084  Fecundity
## 15               5          5.64645       29.0084          2.710084  Fecundity
## 16              -5          5.64645       29.0084          2.710084   Survival
## 17               0          5.64645       29.0084          2.710084   Survival
## 18               5          5.64645       29.0084          2.710084   Survival
##    warm_cold       emmean  lower.HPD  upper.HPD
## 1       Cold -0.121334501 -0.4517610  0.2373984
## 2       Cold -0.091659735 -0.3491781  0.1724248
## 3       Cold -0.062374689 -0.4165708  0.2775442
## 4       Cold  0.283330182 -0.3821255  1.0269214
## 5       Cold -0.400345363 -0.9414361  0.1254571
## 6       Cold -1.089791868 -1.7851123 -0.4350608
## 7       Cold  0.069555305 -1.1210984  1.2306247
## 8       Cold  0.222434159 -0.9097910  1.3525739
## 9       Cold  0.371748070 -0.8646504  1.5842286
## 10      Warm -0.092321044 -0.4500300  0.2429957
## 11      Warm -0.018771553 -0.2447877  0.2108647
## 12      Warm  0.056265266 -0.1755918  0.2826457
## 13      Warm -0.238330760 -0.5884738  0.1208489
## 14      Warm -0.122005369 -0.3686250  0.1259859
## 15      Warm -0.003044981 -0.2146602  0.2373331
## 16      Warm  0.384727184 -0.2682933  1.0356829
## 17      Warm  0.260257792 -0.2973033  0.7901396
## 18      Warm  0.141428516 -0.4144538  0.6911635
# Plot
ggplot() +
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75, 
               lwd=1) +
    geom_quasirandom(data = data,     # Plot effect sizes, scaled by precision
                     aes(x = trait_type:warm_cold, 
                         y = lnCVR, 
                         fill = trait_type:warm_cold, 
                         size = 1/sqrt(var_lnCVR)), 
                     color = "black",
                     shape = 21,
                     width = 0.3, 
                     alpha = 0.3) +
    geom_errorbar(data = filter(emmeans_full_model,
                                assay_temp_diff == "-5"),  # 5 degrees below control (background)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="white",
                  size = 2.75,
                  width = 0.16,
               position = position_nudge(x=-0.25)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "-5"),  # 5 degrees below control (background)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 21,
               size = 4.5, 
               stroke = 2,
               color="white",
               fill = "white",
               position = position_nudge(x=-0.25)) +
    geom_errorbar(data = filter(emmeans_full_model,
                             assay_temp_diff == "-5"), # 5 degrees below control (credible intervals)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="#06B4BA",
                  size = 2,
                  width = 0.12,
               position = position_nudge(x=-0.25)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "-5"), # 5 degrees below control  (point estimates)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 21,
               size = 3.5, 
               stroke = 2,
               color="#06B4BA",
               fill = "white",
               position = position_nudge(x=-0.25)) +

      geom_errorbar(data = filter(emmeans_full_model,
                                assay_temp_diff == "0"),  # control temperature (background)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="white",
                  size = 2.75,
                  width = 0.16,
               position = position_nudge(x=0)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "0"),  # control temperature (background)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 22,
               size = 4.5, 
               stroke = 2,
               color="white",
               fill = "white",
               position = position_nudge(x=0)) +
    geom_errorbar(data = filter(emmeans_full_model,
                             assay_temp_diff == "0"), # control temperature (credible intervals)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="black",
                  size = 2,
                  width = 0.12,
               position = position_nudge(x=0)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "0"), # control temperature (point estimates)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 22,
               size = 3.5, 
               stroke = 2,
               color="black",
               fill = "white",
               position = position_nudge(x=0)) +
  
      geom_errorbar(data = filter(emmeans_full_model,
                                assay_temp_diff == "5"),  # 5 degrees above control (background)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="white",
                  size = 2.75,
                  width = 0.16,
               position = position_nudge(x=0.25)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "5"),  # 5 degrees above control (background)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 23,
               size = 4.5, 
               stroke = 2,
               color="white",
               fill = "white",
               position = position_nudge(x=0.25)) +
    geom_errorbar(data = filter(emmeans_full_model,
                             assay_temp_diff == "5"), # 5 degrees above control (credible intervals)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="#E80756",
                  size = 2,
                  width = 0.12,
               position = position_nudge(x=0.25)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "5"), # 5 degrees above control (point estimates)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 23,
               size = 3.5, 
               stroke = 2,
               color="#E80756",
               fill = "white",
               position = position_nudge(x=0.25)) +
  
    geom_text(data = sample_sizes,  # Sample size annotations 
              aes(x = trait_type:warm_cold, 
                  y = 3,
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1, size = 5, show.legend = FALSE) +
  
    theme_bw() +     # Customize the plot
    labs(y = "lnCVR", x = "") +
    scale_size_continuous(range = c(2, 8))+ 
    scale_fill_manual(values = c("#06B4BA", "#E80756", "#06B4BA", "#E80756", "#06B4BA", "#E80756"))+
    scale_color_manual(values = c("Cold" = "#06B4BA", "Warm" = "#E80756")) +  # Text colour
    theme(text = element_text(size = 20, color = "black"),
          legend.title = ggplot2::element_text(size = 16),
          legend.text = ggplot2::element_text(size = 14),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
          panel.border = element_rect(color = "black", size = 1.5)) +
    guides(fill = "none", size = "none")+
    coord_flip() + 
    ylim(-3, 3)

ggsave(file = "fig/lnCVR_all_moderators_marginal_means.png", width = 12, height = 8, dpi = 500)

Overall trend with assay temperature

# Generate predictions for all assay temperatures
emmeans_full_model_assay <- as.data.frame(emmeans(
  lnCVR_model_all_moderators,
  specs = ~ assay_temp_diff * select_temp_diff * gen_selection * gen_common_garden | trait_type * warm_cold,
  at = list(assay_temp_diff = seq(min(data$assay_temp_diff), max(data$assay_temp_diff), by = 0.5) # Re-acclimated to control, or 5 degrees above/below the contol
  ))) 

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_assay_temp_diff = min(assay_temp_diff),
    max_assay_temp_diff = max(assay_temp_diff)
  )

# Rename variable levels
emmeans_full_model_assay$trait_type <- factor(emmeans_full_model_assay$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_full_model_assay$warm_cold <- factor(emmeans_full_model_assay$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_full_model_assay <- emmeans_full_model_assay %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    assay_temp_diff >= min_assay_temp_diff,
    assay_temp_diff <= max_assay_temp_diff
  )


# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) +  
    geom_vline(xintercept = 0, # Vertical line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data, # Effect sizes, scaled by precision
                  aes(x = assay_temp_diff, 
                      y = lnCVR, 
                      size = 1/sqrt(var_lnCVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_full_model_assay, # Shaded area for credible intervals
                 aes(x = assay_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_full_model_assay,  # Predicted regression line
               aes(y = emmean,
                   x = assay_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) + 
  
    geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  
  facet_wrap(~ trait_type, ncol = 1) + # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Assay temperature difference", y = "lnCVR",
       col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3, 3))

ggsave(file = "fig/lnCVR_all_moderators_assay_temp_diff.png", width = 12, height = 10, dpi = 500)

Changes in trait variance (lnVR)

Overall model

Model specification

# Model specification
formula <- bf(lnVR ~ trait_type -1 + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnVR_model_overall <- brm(formula, 
                           family = gaussian(),
                           data = data, 
                           data2 = list(phylo_matrix = phylo_matrix,
                                        VCV_lnVR = VCV_lnVR),
                           prior = prior,
                           control = list(adapt_delta = 0.99, max_treedepth = 15),
                           iter = 4000, 
                           warmup = 2000,
                           chains = 4, 
                           cores = 4, 
                           seed = 123) 

# Save model
saveRDS(lnVR_model_overall, file = "RData/lnVR_model_overall.rds")

Model output

# Load model
lnVR_model_overall <- readRDS("RData/lnVR_model_overall.rds")

# Display model output
summary(lnVR_model_overall)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnVR ~ trait_type - 1 + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.06     0.00     0.22 1.01      562     1457
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.69      0.03     0.62     0.76 1.00     2391     4360
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.07     0.00     0.27 1.00     1900     2946
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.07      0.06     0.00
## sd(trait_typefecundity)                          0.07      0.06     0.00
## sd(trait_typesurvival)                           0.22      0.13     0.01
## cor(trait_typebody_size,trait_typefecundity)     0.02      0.50    -0.87
## cor(trait_typebody_size,trait_typesurvival)     -0.02      0.50    -0.88
## cor(trait_typefecundity,trait_typesurvival)     -0.03      0.49    -0.87
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.21 1.00     1753     3140
## sd(trait_typefecundity)                          0.22 1.00     1755     2773
## sd(trait_typesurvival)                           0.50 1.00      958     2144
## cor(trait_typebody_size,trait_typefecundity)     0.88 1.00     4376     5091
## cor(trait_typebody_size,trait_typesurvival)      0.88 1.00     2072     3778
## cor(trait_typefecundity,trait_typesurvival)      0.86 1.00     2450     4728
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.18 1.00     2486     3626
## 
## Regression Coefficients:
##                     Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## trait_typebody_size     0.03      0.10    -0.17     0.24 1.00     2172     2851
## trait_typefecundity    -0.06      0.10    -0.25     0.14 1.00     2427     3216
## trait_typesurvival      0.11      0.13    -0.14     0.37 1.00     2994     3681
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnVR_model_overall, summary = TRUE)) %>%
    # Rename categorical variables for cleaner display
rownames_to_column(var = "Parameter") %>%
    mutate(Parameter = gsub("trait_type([a-z_]+)", "\\1", Parameter)) %>%
    # Round numbers to 3 decimal points
mutate(across(c(Estimate, Q2.5, Q97.5), ~round(., 3))) %>%
    select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
    kable() %>%
    kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE) %>%
    row_spec(0, background = "white", color = "black", bold = TRUE) %>%
    kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size 0.030 -0.169 0.243
fecundity -0.057 -0.251 0.143
survival 0.110 -0.137 0.366

Heterogeneity analysis

# Extracting the posterior distribution from the model
posterior <- posterior_samples(lnVR_model_overall)

# Calculate measurement error variance
sigma2_v <- sum(1/diag(VCV_lnVR)) * (length(diag(VCV_lnVR))- 1)/(sum(1/diag(VCV_lnVR))^2 - sum((1/diag(VCV_lnVR))^2))

# Calculate the total variance (including the measurement error variance)
var_total <- posterior$sd_experiment_ID__Intercept +
             posterior$sd_obs__Intercept +
             posterior$sd_phylogeny__Intercept +
             posterior$sd_ref__trait_typebody_size +
             posterior$sd_ref__trait_typefecundity +
             posterior$sd_ref__trait_typesurvival +
             posterior$sd_species__Intercept +
             sigma2_v

# Calculate heterogeneity (I2)
I2 <- list(
    I2_total = (var_total - sigma2_v) / var_total, # Total heterogeneity
    I2_study = (posterior$sd_ref__trait_typebody_size + # Heterogeneity explained by study differences
                posterior$sd_ref__trait_typefecundity +
                posterior$sd_ref__trait_typesurvival) / var_total,
    I2_exp = posterior$sd_experiment_ID__Intercept / var_total, # Heterogeneity explained by experiment differences
    I2_sp = posterior$sd_species__Intercept / var_total, # Heterogeneity explained by species differences
    I2_phylo = posterior$sd_phylogeny__Intercept / var_total, # Heterogeneity explained by phylogenetic relatedness
    I2_obs = posterior$sd_obs__Intercept / var_total # Heterogeneity explained by residual variation

)

# Calculate mean and credible intervals 
summary_table <- t(sapply(I2, function(x) {
    c(Mean = 100*round(mean(x),4), 
      ` ` = 100* round(quantile(x, 0.025),4), 
      ` ` = 100*round(quantile(x, 0.975),4))
}))

# Customise table
summary_table <- summary_table %>%
    as.data.frame() %>% 
    rownames_to_column("Variable") %>%
    mutate(
        Variable = recode(Variable,
                          "I2_total"  = "Total",
                          "I2_study"  = "Study",
                          "I2_exp"    = "Experiment",
                          "I2_sp"     = "Species",
                          "I2_phylo"  = "Phylogeny",
                          "I2_obs"    = "Residual")
    ) %>%
    rename(
        lower_HPD = ` .2.5%`,
        upper_HPD = ` .97.5%`
    ) %>%
  mutate(
    Variable = paste0("I<sup>2</sup><sub>", Variable)   # Create a new column with formatted I² and subscripts
  )


# Display table
kable(summary_table, "html", escape = FALSE, 
      col.names = c("Heterogeneity (%)", "Mean", "Lower HPD", "Upper HPD"),
      align = c('l', 'r', 'r', 'r')) %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, width = "200px", bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Heterogeneity (%) Mean Lower HPD Upper HPD
I2Total 93.16 91.17 94.79
I2Study 25.53 9.36 41.12
I2Experiment 6.51 0.33 14.52
I2Species 4.35 0.18 11.94
I2Phylogeny 6.57 0.27 17.79
I2Residual 50.19 37.83 64.94

Data visualisation

# Generate predictions
emmeans_overall <- as.data.frame(emmeans(lnVR_model_overall, ~ trait_type))

emmeans_overall$trait_type <- factor(emmeans_overall$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))
# Plot
ggplot() +
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75, 
               lwd=1) +
    geom_quasirandom(data = data, # Plot effect sizes, scaled by precision
                     aes(x = trait_type, 
                         y = lnVR, 
                         size = 1/sqrt(var_lnVR)), 
                     fill = "gray75",
                     shape = 21,
                     width = 0.25, 
                     alpha = 0.2) +
    geom_errorbar(data = emmeans_overall,   # Plot the point estimates in white for background
                  aes(ymin = lower.HPD, 
                      ymax = upper.HPD,
                      x = trait_type), 
                  size = 2,
                  width = 0.085,
                  color = "white") +
    geom_point(data = emmeans_overall, # Plot the credible intervals in white for background
               aes(x = trait_type, 
                   y = emmean),
               size = 4.5, 
               stroke = 1.5,
               shape = 21,
               color="white",
               fill = "white") +
    geom_errorbar(data = emmeans_overall,  # Plot the point estimates 
                  aes(x = trait_type, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  size = 1.5,
                  width = 0.075,
                  color = "black") +
    geom_point(data = emmeans_overall, # Plot the credible intervals
               aes(x = trait_type, 
                   y = emmean),
               size = 4,
               shape = 21,
               stroke = 1.5,
               color="black",
               fill = "white") +
    geom_text(data = sample_sizes_traits,  # Sample size annotations 
              aes(x = trait_type, 
                  y = 3.5,
                  label = paste0("k = ", estimates, " (", studies, ")")), 
              hjust = 1, size = 5, show.legend = FALSE) +
    theme_bw() +     # Customize the plot
    labs(y = "lnVR", x = "") +
    scale_size_continuous(range = c(2, 8))+ 
    theme(text = element_text(size = 20, color = "black"),
          legend.title = ggplot2::element_text(size = 16),
          legend.text = ggplot2::element_text(size = 14),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
          panel.border = element_rect(color = "black", size = 1.5)) +
    guides(color = "none", size = "none")+
    coord_flip() + 
    ylim(-3.5, 3.5)

# Save figure
ggsave(file = "fig/lnVR_overall.png", width = 12, height = 7, dpi = 500)

Temperature regime

Model specification

# Model specification
formula <- bf(lnVR ~ trait_type:warm_cold -1 + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnVR_model_warm_cold <- brm(formula, 
                  family = gaussian(),
                  data = data, 
                  data2 = list(phylo_matrix = phylo_matrix,
                               VCV_lnVR = VCV_lnVR),
                  prior = prior,
                  control = list(adapt_delta = 0.99, max_treedepth = 15),
                  iter = 4000, 
                  warmup = 2000,
                  chains = 4, 
                  cores = 4, 
                  seed = 123) 

# Save model
saveRDS(lnVR_model_warm_cold, file = "RData/lnVR_model_warm_cold.rds")

Model output

# Load model
lnVR_model_warm_cold <- readRDS("RData/lnVR_model_warm_cold.rds")

# Display model output 
summary(lnVR_model_warm_cold)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnVR ~ trait_type:warm_cold - 1 + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.10      0.06     0.01     0.22 1.01      699     2066
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.69      0.03     0.63     0.76 1.00     2392     4792
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.07     0.00     0.27 1.00     2421     3746
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.07      0.06     0.00
## sd(trait_typefecundity)                          0.08      0.06     0.00
## sd(trait_typesurvival)                           0.23      0.14     0.01
## cor(trait_typebody_size,trait_typefecundity)     0.02      0.50    -0.87
## cor(trait_typebody_size,trait_typesurvival)     -0.03      0.49    -0.88
## cor(trait_typefecundity,trait_typesurvival)     -0.03      0.49    -0.87
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.21 1.00     2325     4047
## sd(trait_typefecundity)                          0.22 1.00     2191     3451
## sd(trait_typesurvival)                           0.52 1.00     1452     2816
## cor(trait_typebody_size,trait_typefecundity)     0.88 1.00     4568     5550
## cor(trait_typebody_size,trait_typesurvival)      0.85 1.00     2186     4167
## cor(trait_typefecundity,trait_typesurvival)      0.86 1.00     2662     5481
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.17 1.00     2942     5016
## 
## Regression Coefficients:
##                                   Estimate Est.Error l-95% CI u-95% CI Rhat
## trait_typebody_size:warm_coldcold    -0.01      0.14    -0.28     0.26 1.00
## trait_typefecundity:warm_coldcold    -0.17      0.22    -0.59     0.27 1.00
## trait_typesurvival:warm_coldcold     -0.01      0.24    -0.48     0.46 1.00
## trait_typebody_size:warm_coldwarm     0.03      0.11    -0.17     0.25 1.00
## trait_typefecundity:warm_coldwarm    -0.04      0.10    -0.24     0.16 1.00
## trait_typesurvival:warm_coldwarm      0.13      0.14    -0.13     0.41 1.00
##                                   Bulk_ESS Tail_ESS
## trait_typebody_size:warm_coldcold     2592     3441
## trait_typefecundity:warm_coldcold     2897     4305
## trait_typesurvival:warm_coldcold      3848     4863
## trait_typebody_size:warm_coldwarm     2531     3095
## trait_typefecundity:warm_coldwarm     2686     3341
## trait_typesurvival:warm_coldwarm      3777     3791
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnVR_model_warm_cold, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>% 
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) -0.010 -0.280 0.264
fecundity(cold) -0.169 -0.595 0.274
survival(cold) -0.006 -0.485 0.458
body_size(warm) 0.034 -0.173 0.255
fecundity(warm) -0.045 -0.240 0.158
survival(warm) 0.132 -0.133 0.407

Contrasts

# Generate predictions
emms <- emmeans(lnVR_model_warm_cold, specs = ~warm_cold | trait_type)

# Generate contrasts
contrast(emms, method = "pairwise")
## trait_type = body_size:
##  contrast    estimate lower.HPD upper.HPD
##  cold - warm  -0.0441    -0.296     0.214
## 
## trait_type = fecundity:
##  contrast    estimate lower.HPD upper.HPD
##  cold - warm  -0.1252    -0.555     0.306
## 
## trait_type = survival:
##  contrast    estimate lower.HPD upper.HPD
##  cold - warm  -0.1366    -0.621     0.347
## 
## Point estimate displayed: median 
## HPD interval probability: 0.95

Data visualisation

# Generate predictions
emmeans_warm_cold <- as.data.frame(emmeans(lnVR_model_warm_cold, 
                                           specs = ~ warm_cold | trait_type))

emmeans_warm_cold$trait_type <- factor(emmeans_warm_cold$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_warm_cold$warm_cold <- factor(emmeans_warm_cold$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))
# Plot
ggplot() +
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75, 
               lwd=1) +
    geom_quasirandom(data = data,     # Plot effect sizes, scaled by precision
                     aes(x = trait_type:warm_cold, 
                         y = lnVR, 
                         fill = trait_type:warm_cold, 
                         size = 1/sqrt(var_lnVR)), 
                     color = "black",
                     shape = 21,
                     width = 0.25, 
                     alpha = 0.3) +
    geom_errorbar(data = emmeans_warm_cold,  # Plot the point estimates in white for background
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="white",
                  size = 2.5,
                  width = 0.17) +
    geom_point(data = emmeans_warm_cold,  # Plot the credible intervals in white for background
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 21,
               size = 4, 
               stroke = 2,
               color="white",
               fill = "white") +
    geom_errorbar(data = emmeans_warm_cold, # Plot the point estimates 
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="black",
                  size = 2,
                  width = 0.15) +
    geom_point(data = emmeans_warm_cold, # Plot the credible intervals
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 21,
               size = 3.5, 
               stroke = 2,
               color="black",
               fill = "white") +
    geom_text(data = sample_sizes,  # Sample size annotations 
              aes(x = trait_type:warm_cold, 
                  y = 3.5,
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1, size = 5, show.legend = FALSE) +
    theme_bw() +     # Customize the plot
    labs(y = "lnVR", x = "") +
    scale_size_continuous(range = c(2, 8))+ 
#    scale_fill_manual(values = c("#A5F820", "#73B706",  "#9CEFFC", "#06A2BA",  "#FED2ED", "#B90674"))+
    scale_fill_manual(values = c("#06B4BA", "#E80756", "#06B4BA", "#E80756", "#06B4BA", "#E80756"))+
    theme(text = element_text(size = 20, color = "black"),
          legend.title = ggplot2::element_text(size = 16),
          legend.text = ggplot2::element_text(size = 14),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
          panel.border = element_rect(color = "black", size = 1.5)) +
    guides(fill = "none", size = "none")+
    coord_flip() + 
    ylim(-3.5, 3.5)

ggsave(file = "fig/lnVR_warm_cold.png", width = 12, height = 7, dpi = 500)

Assay temperature difference

We calculated the difference between the assay temperature and control temperature (assay_temp_diff) to account for the fact that animals were tested to a different range of temperatures. We also predicted that effects will vary if traits are assayed at colder- or warmer-than-control conditions, depending on the temperature regime. Because the variation in assay temperature generates some nuisance heterogeneity (sensu Noble et al., 2017), the results of subsequent models were provided after controlling for assay temperature differences. In order words, the results of all moderators are conditional on assay temperature, meaning that results are interpretable as the difference between control and selected lines, when animals are tested at the control temperature.

Model specification

# Model specification
formula <- bf(lnVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnVR_model_assay_temp_diff <- brm(formula, 
                                  family = gaussian(),
                                  data = data, 
                                  data2 = list(phylo_matrix = phylo_matrix,
                                               VCV_lnVR = VCV_lnVR),
                                  prior = prior,
                                  control = list(adapt_delta = 0.99, max_treedepth = 15),
                                  iter = 4000, 
                                  warmup = 2000,
                                  chains = 4, 
                                  cores = 4, 
                                  seed = 123) 

# Save model
saveRDS(lnVR_model_assay_temp_diff, file = "RData/lnVR_model_assay_temp_diff.rds")

Model output

# Load model
lnVR_model_assay_temp_diff <- readRDS("RData/lnVR_model_assay_temp_diff.rds")

# Display model output
summary(lnVR_model_assay_temp_diff)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.06     0.01     0.21 1.01      634     1653
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.68      0.03     0.61     0.75 1.00     2347     4647
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.07     0.00     0.27 1.00     1686     3045
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.07      0.06     0.00
## sd(trait_typefecundity)                          0.08      0.06     0.00
## sd(trait_typesurvival)                           0.26      0.14     0.02
## cor(trait_typebody_size,trait_typefecundity)     0.02      0.50    -0.87
## cor(trait_typebody_size,trait_typesurvival)     -0.04      0.51    -0.90
## cor(trait_typefecundity,trait_typesurvival)     -0.02      0.50    -0.88
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.21 1.00     1928     3376
## sd(trait_typefecundity)                          0.23 1.00     1683     2508
## sd(trait_typesurvival)                           0.55 1.00     1160     1944
## cor(trait_typebody_size,trait_typefecundity)     0.88 1.00     3664     4922
## cor(trait_typebody_size,trait_typesurvival)      0.88 1.00     1431     2740
## cor(trait_typefecundity,trait_typesurvival)      0.86 1.00     1714     3633
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.18 1.00     2446     2781
## 
## Regression Coefficients:
##                                                   Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                    -0.02      0.14    -0.30
## trait_typefecundity:warm_coldcold                    -0.40      0.23    -0.85
## trait_typesurvival:warm_coldcold                     -0.02      0.28    -0.57
## trait_typebody_size:warm_coldwarm                     0.04      0.12    -0.20
## trait_typefecundity:warm_coldwarm                    -0.11      0.11    -0.33
## trait_typesurvival:warm_coldwarm                      0.20      0.16    -0.11
## trait_typebody_size:warm_coldcold:assay_temp_diff    -0.02      0.03    -0.07
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.18      0.05    -0.27
## trait_typesurvival:warm_coldcold:assay_temp_diff     -0.01      0.04    -0.10
## trait_typebody_size:warm_coldwarm:assay_temp_diff    -0.00      0.02    -0.04
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.02      0.02    -0.01
## trait_typesurvival:warm_coldwarm:assay_temp_diff     -0.02      0.02    -0.07
##                                                   u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                     0.27 1.00     1835
## trait_typefecundity:warm_coldcold                     0.06 1.00     2263
## trait_typesurvival:warm_coldcold                      0.52 1.00     2709
## trait_typebody_size:warm_coldwarm                     0.28 1.00     1844
## trait_typefecundity:warm_coldwarm                     0.11 1.00     1981
## trait_typesurvival:warm_coldwarm                      0.52 1.00     2465
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.04 1.00     1490
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.09 1.00     2838
## trait_typesurvival:warm_coldcold:assay_temp_diff      0.07 1.00     2706
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.04 1.00     2147
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.05 1.00     1925
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.03 1.00     2693
##                                                   Tail_ESS
## trait_typebody_size:warm_coldcold                     2766
## trait_typefecundity:warm_coldcold                     3742
## trait_typesurvival:warm_coldcold                      4244
## trait_typebody_size:warm_coldwarm                     2563
## trait_typefecundity:warm_coldwarm                     3040
## trait_typesurvival:warm_coldwarm                      3518
## trait_typebody_size:warm_coldcold:assay_temp_diff     2883
## trait_typefecundity:warm_coldcold:assay_temp_diff     4514
## trait_typesurvival:warm_coldcold:assay_temp_diff      4385
## trait_typebody_size:warm_coldwarm:assay_temp_diff     3656
## trait_typefecundity:warm_coldwarm:assay_temp_diff     4007
## trait_typesurvival:warm_coldwarm:assay_temp_diff      4607
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnVR_model_assay_temp_diff, summary = TRUE)) %>%
    # Rename categorical variables for cleaner display
rownames_to_column(var = "Parameter") %>%
    mutate(Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)",
        Parameter), Parameter = gsub("trait_type([a-z_]+)\\(warm\\):assay_temp_diff",
        "\\1(warm): assay_temp_diff", Parameter)) %>%
    # Round numbers to 3 decimal points
mutate(across(c(Estimate, Q2.5, Q97.5), ~round(., 3))) %>%
    select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
    kable() %>%
    kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE) %>%
    row_spec(0, background = "white", color = "black", bold = TRUE) %>%
    kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) -0.020 -0.298 0.274
fecundity(cold) -0.401 -0.854 0.062
survival(cold) -0.022 -0.567 0.525
body_size(warm) 0.037 -0.202 0.282
fecundity(warm) -0.110 -0.332 0.106
survival(warm) 0.196 -0.108 0.517
body_size(cold):assay_temp_diff -0.016 -0.072 0.042
fecundity(cold):assay_temp_diff -0.176 -0.266 -0.085
survival(cold):assay_temp_diff -0.013 -0.097 0.073
body_size(warm):assay_temp_diff -0.001 -0.040 0.039
fecundity(warm):assay_temp_diff 0.020 -0.010 0.050
survival(warm):assay_temp_diff -0.021 -0.068 0.026

Data visualisation

# Generate predictions
emmeans_assay_temp_diff <- as.data.frame(emmeans(
  lnVR_model_assay_temp_diff,
  specs = ~ assay_temp_diff | trait_type * warm_cold,
  at = list(assay_temp_diff = seq(min(data$assay_temp_diff), max(data$assay_temp_diff), by = 0.5)))
  )

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_assay_temp_diff = min(assay_temp_diff),
    max_assay_temp_diff = max(assay_temp_diff)
  )

emmeans_assay_temp_diff$trait_type <- factor(emmeans_assay_temp_diff$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_assay_temp_diff$warm_cold <- factor(emmeans_assay_temp_diff$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_assay_temp_diff <- emmeans_assay_temp_diff %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    assay_temp_diff >= min_assay_temp_diff,
    assay_temp_diff <= max_assay_temp_diff
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) +  
    geom_vline(xintercept = 0, # Vertical line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data, # Effect sizes, scaled by precision
                  aes(x = assay_temp_diff, 
                      y = lnVR, 
                      size = 1/sqrt(var_lnVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_assay_temp_diff, # Shaded area for credible intervals
                 aes(x = assay_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_assay_temp_diff,  # Predicted regression line
               aes(y = emmean,
                   x = assay_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) + 
    geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  
  facet_wrap(~ trait_type, ncol = 1) + # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Assay temperature difference", y = "lnVR",
       col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3.5, 3.5))

ggsave(file = "fig/lnVR_assay_temp_diff.png", width = 12, height = 10, dpi = 500)

Selection temperature

Model specification

# Model specification
formula <- bf(lnVR ~ 0 + trait_type:warm_cold + 
                          trait_type:warm_cold:assay_temp_diff + 
                          trait_type:warm_cold:select_temp_diff + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnVR_model_sel_temp_diff <- brm(formula, 
                                family = gaussian(),
                                data = data, 
                                data2 = list(phylo_matrix = phylo_matrix,
                                             VCV_lnVR = VCV_lnVR),
                                prior = prior,
                                control = list(adapt_delta = 0.99, max_treedepth = 15),
                                iter = 4000, 
                                warmup = 2000,
                                chains = 4, 
                                cores = 4, 
                                seed = 123) 

# Save model
saveRDS(lnVR_model_sel_temp_diff, file = "RData/lnVR_model_sel_temp_diff.rds")

Model output

# Load model
lnVR_model_sel_temp_diff <- readRDS("RData/lnVR_model_sel_temp_diff.rds")

# Display model output
summary(lnVR_model_sel_temp_diff)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:select_temp_diff + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.06     0.00     0.21 1.00      711     1715
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.68      0.03     0.61     0.74 1.00     2566     4622
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.10      0.08     0.00     0.28 1.00     1850     2895
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.07      0.06     0.00
## sd(trait_typefecundity)                          0.08      0.06     0.00
## sd(trait_typesurvival)                           0.28      0.15     0.02
## cor(trait_typebody_size,trait_typefecundity)     0.00      0.50    -0.87
## cor(trait_typebody_size,trait_typesurvival)     -0.02      0.49    -0.89
## cor(trait_typefecundity,trait_typesurvival)      0.01      0.49    -0.87
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.22 1.00     2447     4032
## sd(trait_typefecundity)                          0.23 1.00     2095     3177
## sd(trait_typesurvival)                           0.59 1.00     1183     2257
## cor(trait_typebody_size,trait_typefecundity)     0.88 1.00     3758     4692
## cor(trait_typebody_size,trait_typesurvival)      0.87 1.00     1905     3396
## cor(trait_typefecundity,trait_typesurvival)      0.87 1.00     2001     4219
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.18 1.00     2344     3544
## 
## Regression Coefficients:
##                                                    Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                     -0.23      0.32    -0.85
## trait_typefecundity:warm_coldcold                     -0.14      0.65    -1.40
## trait_typesurvival:warm_coldcold                       0.37      1.37    -2.36
## trait_typebody_size:warm_coldwarm                      0.29      0.19    -0.07
## trait_typefecundity:warm_coldwarm                      0.08      0.16    -0.23
## trait_typesurvival:warm_coldwarm                       0.16      0.25    -0.33
## trait_typebody_size:warm_coldcold:assay_temp_diff     -0.01      0.03    -0.07
## trait_typefecundity:warm_coldcold:assay_temp_diff     -0.19      0.05    -0.29
## trait_typesurvival:warm_coldcold:assay_temp_diff      -0.02      0.05    -0.11
## trait_typebody_size:warm_coldwarm:assay_temp_diff      0.02      0.02    -0.03
## trait_typefecundity:warm_coldwarm:assay_temp_diff      0.03      0.02    -0.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff      -0.03      0.03    -0.08
## trait_typebody_size:warm_coldcold:select_temp_diff     0.04      0.05    -0.06
## trait_typefecundity:warm_coldcold:select_temp_diff    -0.04      0.09    -0.22
## trait_typesurvival:warm_coldcold:select_temp_diff     -0.05      0.18    -0.40
## trait_typebody_size:warm_coldwarm:select_temp_diff    -0.06      0.03    -0.12
## trait_typefecundity:warm_coldwarm:select_temp_diff    -0.05      0.03    -0.11
## trait_typesurvival:warm_coldwarm:select_temp_diff      0.01      0.04    -0.07
##                                                    u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                      0.42 1.00     1863
## trait_typefecundity:warm_coldcold                      1.13 1.00     2747
## trait_typesurvival:warm_coldcold                       3.06 1.00     2812
## trait_typebody_size:warm_coldwarm                      0.66 1.00     1967
## trait_typefecundity:warm_coldwarm                      0.41 1.00     2485
## trait_typesurvival:warm_coldwarm                       0.68 1.00     2641
## trait_typebody_size:warm_coldcold:assay_temp_diff      0.05 1.00     1565
## trait_typefecundity:warm_coldcold:assay_temp_diff     -0.09 1.00     4197
## trait_typesurvival:warm_coldcold:assay_temp_diff       0.07 1.00     2791
## trait_typebody_size:warm_coldwarm:assay_temp_diff      0.06 1.00     2351
## trait_typefecundity:warm_coldwarm:assay_temp_diff      0.07 1.00     2365
## trait_typesurvival:warm_coldwarm:assay_temp_diff       0.03 1.00     2624
## trait_typebody_size:warm_coldcold:select_temp_diff     0.13 1.00     1814
## trait_typefecundity:warm_coldcold:select_temp_diff     0.14 1.00     3165
## trait_typesurvival:warm_coldcold:select_temp_diff      0.29 1.00     2705
## trait_typebody_size:warm_coldwarm:select_temp_diff     0.00 1.00     1896
## trait_typefecundity:warm_coldwarm:select_temp_diff     0.01 1.00     2466
## trait_typesurvival:warm_coldwarm:select_temp_diff      0.08 1.00     2691
##                                                    Tail_ESS
## trait_typebody_size:warm_coldcold                      3140
## trait_typefecundity:warm_coldcold                      4376
## trait_typesurvival:warm_coldcold                       4350
## trait_typebody_size:warm_coldwarm                      3606
## trait_typefecundity:warm_coldwarm                      3682
## trait_typesurvival:warm_coldwarm                       4154
## trait_typebody_size:warm_coldcold:assay_temp_diff      3342
## trait_typefecundity:warm_coldcold:assay_temp_diff      5560
## trait_typesurvival:warm_coldcold:assay_temp_diff       4102
## trait_typebody_size:warm_coldwarm:assay_temp_diff      4493
## trait_typefecundity:warm_coldwarm:assay_temp_diff      3492
## trait_typesurvival:warm_coldwarm:assay_temp_diff       3933
## trait_typebody_size:warm_coldcold:select_temp_diff     2820
## trait_typefecundity:warm_coldcold:select_temp_diff     4803
## trait_typesurvival:warm_coldcold:select_temp_diff      4376
## trait_typebody_size:warm_coldwarm:select_temp_diff     3430
## trait_typefecundity:warm_coldwarm:select_temp_diff     3647
## trait_typesurvival:warm_coldwarm:select_temp_diff      3998
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnVR_model_sel_temp_diff, summary = TRUE)) %>%
    # Rename categorical variables for cleaner display
rownames_to_column(var = "Parameter") %>%
    mutate(Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)",
        Parameter), Parameter = gsub("trait_type([a-z_]+)\\(warm\\):select_temp_diff",
        "\\1(warm): select_temp_diff", Parameter)) %>%
    # Round numbers to 3 decimal points
mutate(across(c(Estimate, Q2.5, Q97.5), ~round(., 3))) %>%
    select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
    kable() %>%
    kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE) %>%
    row_spec(0, background = "white", color = "black", bold = TRUE) %>%
    kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) -0.229 -0.855 0.415
fecundity(cold) -0.137 -1.404 1.133
survival(cold) 0.365 -2.362 3.059
body_size(warm) 0.285 -0.070 0.658
fecundity(warm) 0.076 -0.233 0.406
survival(warm) 0.158 -0.327 0.680
body_size(cold):assay_temp_diff -0.007 -0.068 0.052
fecundity(cold):assay_temp_diff -0.185 -0.285 -0.087
survival(cold):assay_temp_diff -0.018 -0.106 0.071
body_size(warm):assay_temp_diff 0.017 -0.027 0.059
fecundity(warm):assay_temp_diff 0.032 -0.003 0.066
survival(warm):assay_temp_diff -0.025 -0.077 0.026
body_size(cold):select_temp_diff 0.035 -0.062 0.130
fecundity(cold):select_temp_diff -0.040 -0.216 0.137
survival(cold):select_temp_diff -0.052 -0.403 0.294
body_size(warm):select_temp_diff -0.055 -0.115 0.005
fecundity(warm):select_temp_diff -0.051 -0.114 0.011
survival(warm):select_temp_diff 0.008 -0.070 0.080

Data visualisation

# Generate predictions
emmeans_sel_temp_diff <- as.data.frame(emmeans(
  lnVR_model_sel_temp_diff,
  specs = ~ select_temp_diff | trait_type * warm_cold,
  at = list(select_temp_diff = seq(min(data$select_temp_diff), max(data$select_temp_diff), by = 0.5),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_select_temp_diff = min(select_temp_diff),
    max_select_temp_diff = max(select_temp_diff)
  )

emmeans_sel_temp_diff$trait_type <- factor(emmeans_sel_temp_diff$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_sel_temp_diff$warm_cold <- factor(emmeans_sel_temp_diff$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_sel_temp_diff <- emmeans_sel_temp_diff %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    select_temp_diff >= min_select_temp_diff,
    select_temp_diff <= max_select_temp_diff
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = select_temp_diff, 
                      y = lnVR, 
                      size = 1/sqrt(var_lnVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_sel_temp_diff, # Shaded area for credible intervals
                 aes(x = select_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_sel_temp_diff, # Predicted regression line
               aes(y = emmean,
                   x = select_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Selection temperature difference", y = "lnVR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3.5, 3.5))

ggsave(file = "fig/lnVR_sel_temp_diff.png", width = 12, height = 7, dpi = 500)

Number of generations of selection

Model specification

# Model specification
formula <- bf(lnVR ~ 0 + trait_type:warm_cold + 
                          trait_type:warm_cold:assay_temp_diff + 
                          trait_type:warm_cold:scale(gen_selection) + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnVR_model_gen_selection <- brm(formula, 
                                family = gaussian(),
                                data = data, 
                                data2 = list(phylo_matrix = phylo_matrix,
                                             VCV_lnVR = VCV_lnVR),
                                prior = prior,
                                control = list(adapt_delta = 0.99, max_treedepth = 15),
                                iter = 4000, 
                                warmup = 2000,
                                chains = 4, 
                                cores = 4, 
                                seed = 123) 
# Save model
saveRDS(lnVR_model_gen_selection, file = "RData/lnVR_model_gen_selection.rds")

Model output

# Load model
lnVR_model_gen_selection <- readRDS("RData/lnVR_model_gen_selection.rds")

# Display model output 
summary(lnVR_model_gen_selection)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:scale(gen_selection) + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.06     0.00     0.21 1.01      903     2637
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.68      0.03     0.61     0.75 1.00     3178     4871
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.07     0.00     0.27 1.00     3124     3917
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.07      0.06     0.00
## sd(trait_typefecundity)                          0.08      0.06     0.00
## sd(trait_typesurvival)                           0.30      0.15     0.03
## cor(trait_typebody_size,trait_typefecundity)     0.01      0.50    -0.87
## cor(trait_typebody_size,trait_typesurvival)     -0.02      0.50    -0.88
## cor(trait_typefecundity,trait_typesurvival)     -0.04      0.49    -0.88
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.22 1.00     2998     4012
## sd(trait_typefecundity)                          0.23 1.00     2675     4058
## sd(trait_typesurvival)                           0.61 1.00     1224     1341
## cor(trait_typebody_size,trait_typefecundity)     0.88 1.00     5312     5802
## cor(trait_typebody_size,trait_typesurvival)      0.88 1.00     2069     3948
## cor(trait_typefecundity,trait_typesurvival)      0.86 1.00     2585     4515
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.17 1.00     3260     4818
## 
## Regression Coefficients:
##                                                      Estimate Est.Error
## trait_typebody_size:warm_coldcold                       -0.08      0.15
## trait_typefecundity:warm_coldcold                       -0.31      0.28
## trait_typesurvival:warm_coldcold                         0.05      0.35
## trait_typebody_size:warm_coldwarm                        0.03      0.12
## trait_typefecundity:warm_coldwarm                       -0.18      0.12
## trait_typesurvival:warm_coldwarm                         0.21      0.20
## trait_typebody_size:warm_coldcold:assay_temp_diff       -0.01      0.03
## trait_typefecundity:warm_coldcold:assay_temp_diff       -0.19      0.05
## trait_typesurvival:warm_coldcold:assay_temp_diff        -0.02      0.05
## trait_typebody_size:warm_coldwarm:assay_temp_diff       -0.00      0.02
## trait_typefecundity:warm_coldwarm:assay_temp_diff        0.03      0.02
## trait_typesurvival:warm_coldwarm:assay_temp_diff        -0.02      0.02
## trait_typebody_size:warm_coldcold:scalegen_selection     0.09      0.11
## trait_typefecundity:warm_coldcold:scalegen_selection    -0.13      0.16
## trait_typesurvival:warm_coldcold:scalegen_selection     -0.09      0.20
## trait_typebody_size:warm_coldwarm:scalegen_selection    -0.03      0.07
## trait_typefecundity:warm_coldwarm:scalegen_selection    -0.18      0.12
## trait_typesurvival:warm_coldwarm:scalegen_selection      0.04      0.30
##                                                      l-95% CI u-95% CI Rhat
## trait_typebody_size:warm_coldcold                       -0.38     0.22 1.00
## trait_typefecundity:warm_coldcold                       -0.86     0.24 1.00
## trait_typesurvival:warm_coldcold                        -0.66     0.74 1.00
## trait_typebody_size:warm_coldwarm                       -0.21     0.27 1.00
## trait_typefecundity:warm_coldwarm                       -0.41     0.05 1.00
## trait_typesurvival:warm_coldwarm                        -0.17     0.60 1.00
## trait_typebody_size:warm_coldcold:assay_temp_diff       -0.07     0.05 1.00
## trait_typefecundity:warm_coldcold:assay_temp_diff       -0.28    -0.09 1.00
## trait_typesurvival:warm_coldcold:assay_temp_diff        -0.11     0.07 1.00
## trait_typebody_size:warm_coldwarm:assay_temp_diff       -0.04     0.04 1.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff       -0.01     0.06 1.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff        -0.07     0.02 1.00
## trait_typebody_size:warm_coldcold:scalegen_selection    -0.12     0.30 1.00
## trait_typefecundity:warm_coldcold:scalegen_selection    -0.43     0.19 1.00
## trait_typesurvival:warm_coldcold:scalegen_selection     -0.47     0.30 1.00
## trait_typebody_size:warm_coldwarm:scalegen_selection    -0.17     0.10 1.00
## trait_typefecundity:warm_coldwarm:scalegen_selection    -0.42     0.05 1.00
## trait_typesurvival:warm_coldwarm:scalegen_selection     -0.56     0.64 1.00
##                                                      Bulk_ESS Tail_ESS
## trait_typebody_size:warm_coldcold                        3963     4998
## trait_typefecundity:warm_coldcold                        5269     5838
## trait_typesurvival:warm_coldcold                         4825     5100
## trait_typebody_size:warm_coldwarm                        3397     4617
## trait_typefecundity:warm_coldwarm                        3245     4514
## trait_typesurvival:warm_coldwarm                         4858     5210
## trait_typebody_size:warm_coldcold:assay_temp_diff        2958     4256
## trait_typefecundity:warm_coldcold:assay_temp_diff        5388     5860
## trait_typesurvival:warm_coldcold:assay_temp_diff         4795     5591
## trait_typebody_size:warm_coldwarm:assay_temp_diff        3909     5356
## trait_typefecundity:warm_coldwarm:assay_temp_diff        3454     4427
## trait_typesurvival:warm_coldwarm:assay_temp_diff         5143     6729
## trait_typebody_size:warm_coldcold:scalegen_selection     3563     4687
## trait_typefecundity:warm_coldcold:scalegen_selection     5708     5582
## trait_typesurvival:warm_coldcold:scalegen_selection      4861     5581
## trait_typebody_size:warm_coldwarm:scalegen_selection     4280     5411
## trait_typefecundity:warm_coldwarm:scalegen_selection     3373     4641
## trait_typesurvival:warm_coldwarm:scalegen_selection      5155     5260
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnVR_model_gen_selection, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((cold|warm)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter),
    # Remove "scale" from gen_selection
    Parameter = gsub("scalegen_selection", "gen_selection", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) -0.084 -0.383 0.217
fecundity(cold) -0.307 -0.856 0.238
survival(cold) 0.049 -0.664 0.737
body_size(warm) 0.031 -0.214 0.271
fecundity(warm) -0.182 -0.413 0.051
survival(warm) 0.213 -0.167 0.600
body_size(cold):assay_temp_diff -0.008 -0.069 0.054
fecundity(cold):assay_temp_diff -0.188 -0.283 -0.089
survival(cold):assay_temp_diff -0.019 -0.109 0.071
body_size(warm):assay_temp_diff -0.001 -0.041 0.038
fecundity(warm):assay_temp_diff 0.026 -0.006 0.058
survival(warm):assay_temp_diff -0.023 -0.070 0.023
body_size(cold):gen_selection 0.088 -0.119 0.303
fecundity(cold):gen_selection -0.127 -0.427 0.186
survival(cold):gen_selection -0.088 -0.474 0.301
body_size(warm):gen_selection -0.031 -0.169 0.102
fecundity(warm):gen_selection -0.184 -0.424 0.054
survival(warm):gen_selection 0.038 -0.563 0.635

Data visualisation

# Generate predictions
emmeans_gen_selection <- as.data.frame(emmeans(
  lnVR_model_gen_selection,
  specs = ~ gen_selection | trait_type * warm_cold,
  at = list(gen_selection = seq(min(data$gen_selection), max(data$gen_selection), by = 1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_gen_selection = min(gen_selection),
    max_gen_selection = max(gen_selection)
  )

emmeans_gen_selection$trait_type <- factor(emmeans_gen_selection$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_gen_selection$warm_cold <- factor(emmeans_gen_selection$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_gen_selection <- emmeans_gen_selection %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    gen_selection >= min_gen_selection,
    gen_selection <= max_gen_selection
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = gen_selection, 
                      y = lnVR, 
                      size = 1/sqrt(var_lnVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_gen_selection, # Shaded area for credible intervals
                 aes(x = gen_selection,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_gen_selection, # Predicted regression line
               aes(y = emmean,
                   x = gen_selection,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Number of generations of selection", y = "lnVR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3.5, 3.5),
                    xlim = c(0, 150))

ggsave(file = "fig/lnVR_gen_selection.png", width = 12, height = 7, dpi = 500)

Number of generations of common garden

Model specification

# Model specification
formula <- bf(lnVR ~ 0 + trait_type:warm_cold + 
                          trait_type:warm_cold:assay_temp_diff + 
                          trait_type:warm_cold:scale(gen_common_garden) + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnVR_model_gen_common_garden <- brm(formula, 
                                family = gaussian(),
                                data = data, 
                                data2 = list(phylo_matrix = phylo_matrix,
                                             VCV_lnVR = VCV_lnVR),
                                prior = prior,
                                control = list(adapt_delta = 0.99, max_treedepth = 15),
                                iter = 4000, 
                                warmup = 2000,
                                chains = 4, 
                                cores = 4, 
                                seed = 123) 
# Save model
saveRDS(lnVR_model_gen_common_garden, file = "RData/lnVR_model_gen_common_garden.rds")

Model output

# Load model
lnVR_model_gen_common_garden <- readRDS("RData/lnVR_model_gen_common_garden.rds")

# Display model output 
summary(lnVR_model_gen_common_garden)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:scale(gen_common_garden) + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.06     0.00     0.22 1.00      734     2267
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.68      0.03     0.62     0.75 1.00     2503     3863
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.10      0.08     0.00     0.30 1.00     1922     2831
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.08      0.06     0.00
## sd(trait_typefecundity)                          0.08      0.07     0.00
## sd(trait_typesurvival)                           0.29      0.15     0.03
## cor(trait_typebody_size,trait_typefecundity)     0.01      0.50    -0.86
## cor(trait_typebody_size,trait_typesurvival)     -0.04      0.50    -0.90
## cor(trait_typefecundity,trait_typesurvival)     -0.03      0.49    -0.89
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.23 1.00     1856     2694
## sd(trait_typefecundity)                          0.24 1.00     1538     2748
## sd(trait_typesurvival)                           0.61 1.01     1068     1667
## cor(trait_typebody_size,trait_typefecundity)     0.87 1.00     3422     5458
## cor(trait_typebody_size,trait_typesurvival)      0.87 1.00     1339     2732
## cor(trait_typefecundity,trait_typesurvival)      0.85 1.00     1742     4248
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.18 1.00     2330     3367
## 
## Regression Coefficients:
##                                                          Estimate Est.Error
## trait_typebody_size:warm_coldcold                           -0.01      0.15
## trait_typefecundity:warm_coldcold                           -0.37      0.23
## trait_typesurvival:warm_coldcold                            -0.03      0.30
## trait_typebody_size:warm_coldwarm                            0.02      0.12
## trait_typefecundity:warm_coldwarm                           -0.11      0.11
## trait_typesurvival:warm_coldwarm                             0.20      0.17
## trait_typebody_size:warm_coldcold:assay_temp_diff           -0.02      0.03
## trait_typefecundity:warm_coldcold:assay_temp_diff           -0.18      0.05
## trait_typesurvival:warm_coldcold:assay_temp_diff            -0.01      0.05
## trait_typebody_size:warm_coldwarm:assay_temp_diff           -0.00      0.02
## trait_typefecundity:warm_coldwarm:assay_temp_diff            0.02      0.02
## trait_typesurvival:warm_coldwarm:assay_temp_diff            -0.02      0.02
## trait_typebody_size:warm_coldcold:scalegen_common_garden    -0.06      0.58
## trait_typefecundity:warm_coldcold:scalegen_common_garden     0.95      0.95
## trait_typesurvival:warm_coldcold:scalegen_common_garden      0.06      0.82
## trait_typebody_size:warm_coldwarm:scalegen_common_garden    -0.28      0.45
## trait_typefecundity:warm_coldwarm:scalegen_common_garden    -0.00      0.04
## trait_typesurvival:warm_coldwarm:scalegen_common_garden      0.08      0.68
##                                                          l-95% CI u-95% CI Rhat
## trait_typebody_size:warm_coldcold                           -0.30     0.29 1.00
## trait_typefecundity:warm_coldcold                           -0.83     0.09 1.00
## trait_typesurvival:warm_coldcold                            -0.60     0.57 1.00
## trait_typebody_size:warm_coldwarm                           -0.21     0.27 1.00
## trait_typefecundity:warm_coldwarm                           -0.33     0.12 1.00
## trait_typesurvival:warm_coldwarm                            -0.12     0.54 1.00
## trait_typebody_size:warm_coldcold:assay_temp_diff           -0.07     0.04 1.00
## trait_typefecundity:warm_coldcold:assay_temp_diff           -0.27    -0.09 1.00
## trait_typesurvival:warm_coldcold:assay_temp_diff            -0.10     0.08 1.00
## trait_typebody_size:warm_coldwarm:assay_temp_diff           -0.04     0.04 1.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff           -0.01     0.05 1.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff            -0.07     0.03 1.00
## trait_typebody_size:warm_coldcold:scalegen_common_garden    -1.18     1.07 1.00
## trait_typefecundity:warm_coldcold:scalegen_common_garden    -0.92     2.80 1.00
## trait_typesurvival:warm_coldcold:scalegen_common_garden     -1.57     1.70 1.00
## trait_typebody_size:warm_coldwarm:scalegen_common_garden    -1.15     0.59 1.00
## trait_typefecundity:warm_coldwarm:scalegen_common_garden    -0.07     0.07 1.00
## trait_typesurvival:warm_coldwarm:scalegen_common_garden     -1.25     1.42 1.00
##                                                          Bulk_ESS Tail_ESS
## trait_typebody_size:warm_coldcold                            1923     2788
## trait_typefecundity:warm_coldcold                            2798     4039
## trait_typesurvival:warm_coldcold                             2314     3598
## trait_typebody_size:warm_coldwarm                            1856     2840
## trait_typefecundity:warm_coldwarm                            1929     3018
## trait_typesurvival:warm_coldwarm                             2686     2899
## trait_typebody_size:warm_coldcold:assay_temp_diff            1669     2727
## trait_typefecundity:warm_coldcold:assay_temp_diff            3397     4792
## trait_typesurvival:warm_coldcold:assay_temp_diff             2894     4083
## trait_typebody_size:warm_coldwarm:assay_temp_diff            2413     3406
## trait_typefecundity:warm_coldwarm:assay_temp_diff            2015     3520
## trait_typesurvival:warm_coldwarm:assay_temp_diff             3059     4817
## trait_typebody_size:warm_coldcold:scalegen_common_garden     2614     4742
## trait_typefecundity:warm_coldcold:scalegen_common_garden     4186     5157
## trait_typesurvival:warm_coldcold:scalegen_common_garden      3684     4803
## trait_typebody_size:warm_coldwarm:scalegen_common_garden     2435     4001
## trait_typefecundity:warm_coldwarm:scalegen_common_garden     2949     4546
## trait_typesurvival:warm_coldwarm:scalegen_common_garden      3369     4401
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnVR_model_gen_common_garden, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((cold|warm)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter),
    # Remove "scale" from gen_selection
    Parameter = gsub("scalegen_common_garden", "gen_common_garden", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) -0.014 -0.295 0.286
fecundity(cold) -0.371 -0.833 0.087
survival(cold) -0.026 -0.598 0.566
body_size(warm) 0.025 -0.215 0.274
fecundity(warm) -0.108 -0.334 0.121
survival(warm) 0.204 -0.119 0.545
body_size(cold):assay_temp_diff -0.015 -0.073 0.041
fecundity(cold):assay_temp_diff -0.181 -0.273 -0.087
survival(cold):assay_temp_diff -0.013 -0.102 0.077
body_size(warm):assay_temp_diff -0.002 -0.042 0.036
fecundity(warm):assay_temp_diff 0.020 -0.011 0.051
survival(warm):assay_temp_diff -0.021 -0.069 0.027
body_size(cold):gen_common_garden -0.064 -1.182 1.067
fecundity(cold):gen_common_garden 0.954 -0.918 2.804
survival(cold):gen_common_garden 0.063 -1.566 1.701
body_size(warm):gen_common_garden -0.285 -1.152 0.585
fecundity(warm):gen_common_garden -0.001 -0.073 0.069
survival(warm):gen_common_garden 0.083 -1.248 1.418

Data visualisation

# Generate predictions
emmeans_gen_common_garden <- as.data.frame(emmeans(
  lnVR_model_gen_common_garden,
  specs = ~ gen_common_garden | trait_type * warm_cold,
  at = list(gen_common_garden = seq(min(data$gen_common_garden), max(data$gen_common_garden), by = 1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_gen_common_garden = min(gen_common_garden),
    max_gen_common_garden = max(gen_common_garden)
  )

emmeans_gen_common_garden$trait_type <- factor(emmeans_gen_common_garden$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_gen_common_garden$warm_cold <- factor(emmeans_gen_common_garden$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_gen_common_garden <- emmeans_gen_common_garden %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    gen_common_garden >= min_gen_common_garden,
    gen_common_garden <= max_gen_common_garden
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = gen_common_garden, 
                      y = lnVR, 
                      size = 1/sqrt(var_lnVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_gen_common_garden, # Shaded area for credible intervals
                 aes(x = gen_common_garden,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_gen_common_garden, # Predicted regression line
               aes(y = emmean,
                   x = gen_common_garden,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Number of generations of common garden", y = "lnVR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3.5, 3.5),
                    xlim = c(0, 12))

ggsave(file = "fig/lnVR_gen_common_garden.png", width = 12, height = 7, dpi = 500)

Population size

Model specification

# Model specification
formula <- bf(lnVR ~ 0 + trait_type:warm_cold + 
                          trait_type:warm_cold:assay_temp_diff + 
                          trait_type:warm_cold:scale(pop_size) + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnVR_model_pop_size <- brm(formula, 
                                family = gaussian(),
                                data = data, 
                                data2 = list(phylo_matrix = phylo_matrix,
                                             VCV_lnVR = VCV_lnVR),
                                prior = prior,
                                control = list(adapt_delta = 0.99, max_treedepth = 15),
                                iter = 4000, 
                                warmup = 2000,
                                chains = 4, 
                                cores = 4, 
                                seed = 123) 
# Save model
saveRDS(lnVR_model_pop_size, file = "RData/lnVR_model_pop_size.rds")

Model output

# Load model
lnVR_model_pop_size <- readRDS("RData/lnVR_model_pop_size.rds")

# Display model output 
summary(lnVR_model_pop_size)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:scale(pop_size) + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnVR) 
##    Data: data (Number of observations: 426) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 79) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.07      0.05     0.00     0.18 1.00      952     2315
## 
## ~obs (Number of levels: 426) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.36      0.03     0.31     0.42 1.00     2535     4161
## 
## ~phylogeny (Number of levels: 22) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.08      0.06     0.00     0.24 1.00     2431     3797
## 
## ~ref (Number of levels: 41) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.07      0.06     0.00
## sd(trait_typefecundity)                          0.10      0.07     0.00
## sd(trait_typesurvival)                           0.25      0.12     0.03
## cor(trait_typebody_size,trait_typefecundity)     0.05      0.50    -0.87
## cor(trait_typebody_size,trait_typesurvival)     -0.10      0.50    -0.90
## cor(trait_typefecundity,trait_typesurvival)      0.02      0.49    -0.87
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.21 1.00     1826     2849
## sd(trait_typefecundity)                          0.25 1.00     1356     2414
## sd(trait_typesurvival)                           0.50 1.00     1478     1451
## cor(trait_typebody_size,trait_typefecundity)     0.89 1.00     2645     4060
## cor(trait_typebody_size,trait_typesurvival)      0.84 1.00     1484     2835
## cor(trait_typefecundity,trait_typesurvival)      0.87 1.00     1913     3967
## 
## ~species (Number of levels: 22) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.17 1.00     2499     3232
## 
## Regression Coefficients:
##                                                   Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                     0.04      0.12    -0.19
## trait_typefecundity:warm_coldcold                    -0.37      0.17    -0.70
## trait_typesurvival:warm_coldcold                     -0.09      0.21    -0.51
## trait_typebody_size:warm_coldwarm                    -0.01      0.10    -0.20
## trait_typefecundity:warm_coldwarm                    -0.06      0.09    -0.24
## trait_typesurvival:warm_coldwarm                      0.03      0.13    -0.21
## trait_typebody_size:warm_coldcold:assay_temp_diff    -0.00      0.02    -0.04
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.17      0.03    -0.24
## trait_typesurvival:warm_coldcold:assay_temp_diff     -0.02      0.03    -0.08
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.00      0.01    -0.02
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.00      0.01    -0.02
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.00      0.02    -0.03
## trait_typebody_size:warm_coldcold:scalepop_size      -0.11      0.08    -0.27
## trait_typefecundity:warm_coldcold:scalepop_size       0.04      0.15    -0.24
## trait_typesurvival:warm_coldcold:scalepop_size        0.06      0.21    -0.35
## trait_typebody_size:warm_coldwarm:scalepop_size      -0.02      0.05    -0.11
## trait_typefecundity:warm_coldwarm:scalepop_size      -0.06      0.06    -0.19
## trait_typesurvival:warm_coldwarm:scalepop_size       -0.03      0.10    -0.23
##                                                   u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                     0.27 1.00     2129
## trait_typefecundity:warm_coldcold                    -0.03 1.00     3984
## trait_typesurvival:warm_coldcold                      0.33 1.00     3648
## trait_typebody_size:warm_coldwarm                     0.19 1.00     2557
## trait_typefecundity:warm_coldwarm                     0.12 1.00     2826
## trait_typesurvival:warm_coldwarm                      0.30 1.00     2914
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.04 1.00     2644
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.10 1.00     4468
## trait_typesurvival:warm_coldcold:assay_temp_diff      0.04 1.00     4081
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.03 1.00     3677
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.03 1.00     3902
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.04 1.00     4262
## trait_typebody_size:warm_coldcold:scalepop_size       0.04 1.00     2382
## trait_typefecundity:warm_coldcold:scalepop_size       0.33 1.00     3577
## trait_typesurvival:warm_coldcold:scalepop_size        0.46 1.00     4371
## trait_typebody_size:warm_coldwarm:scalepop_size       0.08 1.00     3030
## trait_typefecundity:warm_coldwarm:scalepop_size       0.06 1.00     3293
## trait_typesurvival:warm_coldwarm:scalepop_size        0.16 1.00     3812
##                                                   Tail_ESS
## trait_typebody_size:warm_coldcold                     3634
## trait_typefecundity:warm_coldcold                     4760
## trait_typesurvival:warm_coldcold                      4534
## trait_typebody_size:warm_coldwarm                     3089
## trait_typefecundity:warm_coldwarm                     3984
## trait_typesurvival:warm_coldwarm                      3027
## trait_typebody_size:warm_coldcold:assay_temp_diff     4285
## trait_typefecundity:warm_coldcold:assay_temp_diff     5294
## trait_typesurvival:warm_coldcold:assay_temp_diff      4976
## trait_typebody_size:warm_coldwarm:assay_temp_diff     4957
## trait_typefecundity:warm_coldwarm:assay_temp_diff     5487
## trait_typesurvival:warm_coldwarm:assay_temp_diff      5544
## trait_typebody_size:warm_coldcold:scalepop_size       4168
## trait_typefecundity:warm_coldcold:scalepop_size       4757
## trait_typesurvival:warm_coldcold:scalepop_size        4857
## trait_typebody_size:warm_coldwarm:scalepop_size       4325
## trait_typefecundity:warm_coldwarm:scalepop_size       4563
## trait_typesurvival:warm_coldwarm:scalepop_size        4889
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnVR_model_pop_size, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((cold|warm)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter),
    # Remove "scale" from pop_size
    Parameter = gsub("scalepop_size", "pop_size", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) 0.037 -0.193 0.274
fecundity(cold) -0.371 -0.702 -0.030
survival(cold) -0.093 -0.513 0.328
body_size(warm) -0.005 -0.197 0.187
fecundity(warm) -0.062 -0.239 0.119
survival(warm) 0.031 -0.214 0.295
body_size(cold):assay_temp_diff 0.000 -0.040 0.039
fecundity(cold):assay_temp_diff -0.171 -0.240 -0.103
survival(cold):assay_temp_diff -0.019 -0.080 0.042
body_size(warm):assay_temp_diff 0.005 -0.024 0.033
fecundity(warm):assay_temp_diff 0.004 -0.018 0.027
survival(warm):assay_temp_diff 0.003 -0.033 0.038
body_size(cold):pop_size -0.113 -0.268 0.041
fecundity(cold):pop_size 0.043 -0.244 0.329
survival(cold):pop_size 0.056 -0.350 0.462
body_size(warm):pop_size -0.016 -0.115 0.083
fecundity(warm):pop_size -0.060 -0.187 0.060
survival(warm):pop_size -0.030 -0.230 0.160

Data visualisation

# Generate predictions
emmeans_pop_size <- as.data.frame(emmeans(
  lnVR_model_pop_size,
  specs = ~ pop_size | trait_type * warm_cold,
  at = list(pop_size = seq(min(data$pop_size, na.rm=T), max(data$pop_size, na.rm=T), by = 50),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_pop_size = min(pop_size, na.rm=T),
    max_pop_size = max(pop_size, na.rm=T)
  )

emmeans_pop_size$trait_type <- factor(emmeans_pop_size$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_pop_size$warm_cold <- factor(emmeans_pop_size$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_pop_size <- emmeans_pop_size %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    pop_size >= min_pop_size,
    pop_size <= max_pop_size
  )

# Calculate sample sizes and study counts for population size
sample_sizes_pop_size <- data %>%
  filter(is.na(pop_size)==FALSE) %>% 
  group_by(trait_type, warm_cold) %>%
  summarise(
    estimates = n(),
    studies = n_distinct(ref)
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = pop_size, 
                      y = lnVR, 
                      size = 1/sqrt(var_lnVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_pop_size, # Shaded area for credible intervals
                 aes(x = pop_size,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_pop_size, # Predicted regression line
               aes(y = emmean,
                   x = pop_size,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes_pop_size, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Population size", y = "lnVR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    ylim(-3.5, 3.5)

ggsave(file = "fig/lnVR_pop_size.png", width = 12, height = 7, dpi = 500)

All moderators

Model specification

# Model specification
formula <- bf(lnVR ~ 0 + trait_type:warm_cold + 
                trait_type:warm_cold:assay_temp_diff + 
                trait_type:warm_cold:scale(select_temp_diff) +
                trait_type:warm_cold:scale(gen_selection) + 
                trait_type:warm_cold:scale(gen_common_garden) + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnVR_model_all_moderators <- brm(formula, 
                                  family = gaussian(),
                                  data = data, 
                                  data2 = list(phylo_matrix = phylo_matrix,
                                               VCV_lnVR = VCV_lnVR),
                                  prior = prior,
                                  control = list(adapt_delta = 0.99, max_treedepth = 15),
                                  iter = 4000, 
                                  warmup = 2000,
                                  chains = 4, 
                                  cores = 4, 
                                  seed = 123) 

# Save model
saveRDS(lnVR_model_all_moderators, file = "RData/lnVR_model_all_moderators.rds")

Model output

# Load model
lnVR_model_all_moderators <- readRDS("RData/lnVR_model_all_moderators.rds")

# Display model output 
summary(lnVR_model_all_moderators)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:scale(select_temp_diff) + trait_type:warm_cold:scale(gen_selection) + trait_type:warm_cold:scale(gen_common_garden) + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.10      0.06     0.01     0.23 1.01      897     2200
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.68      0.03     0.62     0.75 1.00     3468     5446
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.10      0.08     0.00     0.29 1.00     2518     3463
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.08      0.06     0.00
## sd(trait_typefecundity)                          0.08      0.07     0.00
## sd(trait_typesurvival)                           0.35      0.18     0.03
## cor(trait_typebody_size,trait_typefecundity)    -0.01      0.51    -0.88
## cor(trait_typebody_size,trait_typesurvival)     -0.02      0.50    -0.88
## cor(trait_typefecundity,trait_typesurvival)     -0.01      0.49    -0.87
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.24 1.00     2879     3802
## sd(trait_typefecundity)                          0.25 1.00     2273     3743
## sd(trait_typesurvival)                           0.72 1.00     1272     1684
## cor(trait_typebody_size,trait_typefecundity)     0.89 1.00     5698     5658
## cor(trait_typebody_size,trait_typesurvival)      0.87 1.00     1652     3796
## cor(trait_typefecundity,trait_typesurvival)      0.86 1.00     2195     4761
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.19 1.00     3341     4704
## 
## Regression Coefficients:
##                                                          Estimate Est.Error
## trait_typebody_size:warm_coldcold                           -0.08      0.16
## trait_typefecundity:warm_coldcold                           -0.28      0.30
## trait_typesurvival:warm_coldcold                             0.11      0.50
## trait_typebody_size:warm_coldwarm                           -0.04      0.13
## trait_typefecundity:warm_coldwarm                           -0.23      0.13
## trait_typesurvival:warm_coldwarm                             0.22      0.22
## trait_typebody_size:warm_coldcold:assay_temp_diff           -0.00      0.03
## trait_typefecundity:warm_coldcold:assay_temp_diff           -0.20      0.05
## trait_typesurvival:warm_coldcold:assay_temp_diff            -0.02      0.05
## trait_typebody_size:warm_coldwarm:assay_temp_diff            0.02      0.02
## trait_typefecundity:warm_coldwarm:assay_temp_diff            0.03      0.02
## trait_typesurvival:warm_coldwarm:assay_temp_diff            -0.03      0.03
## trait_typebody_size:warm_coldcold:scaleselect_temp_diff      0.09      0.18
## trait_typefecundity:warm_coldcold:scaleselect_temp_diff     -0.15      0.29
## trait_typesurvival:warm_coldcold:scaleselect_temp_diff      -0.03      0.85
## trait_typebody_size:warm_coldwarm:scaleselect_temp_diff     -0.18      0.10
## trait_typefecundity:warm_coldwarm:scaleselect_temp_diff     -0.11      0.11
## trait_typesurvival:warm_coldwarm:scaleselect_temp_diff       0.01      0.14
## trait_typebody_size:warm_coldcold:scalegen_selection         0.07      0.12
## trait_typefecundity:warm_coldcold:scalegen_selection        -0.08      0.17
## trait_typesurvival:warm_coldcold:scalegen_selection         -0.11      0.35
## trait_typebody_size:warm_coldwarm:scalegen_selection        -0.04      0.07
## trait_typefecundity:warm_coldwarm:scalegen_selection        -0.13      0.14
## trait_typesurvival:warm_coldwarm:scalegen_selection          0.03      0.36
## trait_typebody_size:warm_coldcold:scalegen_common_garden    -0.05      0.62
## trait_typefecundity:warm_coldcold:scalegen_common_garden     0.78      1.06
## trait_typesurvival:warm_coldcold:scalegen_common_garden     -0.18      1.24
## trait_typebody_size:warm_coldwarm:scalegen_common_garden    -0.17      0.46
## trait_typefecundity:warm_coldwarm:scalegen_common_garden     0.01      0.04
## trait_typesurvival:warm_coldwarm:scalegen_common_garden      0.01      0.75
##                                                          l-95% CI u-95% CI Rhat
## trait_typebody_size:warm_coldcold                           -0.38     0.23 1.00
## trait_typefecundity:warm_coldcold                           -0.88     0.31 1.00
## trait_typesurvival:warm_coldcold                            -0.84     1.09 1.00
## trait_typebody_size:warm_coldwarm                           -0.29     0.23 1.00
## trait_typefecundity:warm_coldwarm                           -0.49     0.03 1.00
## trait_typesurvival:warm_coldwarm                            -0.19     0.67 1.00
## trait_typebody_size:warm_coldcold:assay_temp_diff           -0.06     0.06 1.00
## trait_typefecundity:warm_coldcold:assay_temp_diff           -0.30    -0.09 1.00
## trait_typesurvival:warm_coldcold:assay_temp_diff            -0.11     0.08 1.00
## trait_typebody_size:warm_coldwarm:assay_temp_diff           -0.03     0.06 1.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff           -0.00     0.07 1.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff            -0.08     0.03 1.00
## trait_typebody_size:warm_coldcold:scaleselect_temp_diff     -0.25     0.43 1.00
## trait_typefecundity:warm_coldcold:scaleselect_temp_diff     -0.72     0.44 1.00
## trait_typesurvival:warm_coldcold:scaleselect_temp_diff      -1.76     1.61 1.00
## trait_typebody_size:warm_coldwarm:scaleselect_temp_diff     -0.38     0.03 1.00
## trait_typefecundity:warm_coldwarm:scaleselect_temp_diff     -0.33     0.11 1.00
## trait_typesurvival:warm_coldwarm:scaleselect_temp_diff      -0.29     0.28 1.00
## trait_typebody_size:warm_coldcold:scalegen_selection        -0.17     0.31 1.00
## trait_typefecundity:warm_coldcold:scalegen_selection        -0.42     0.26 1.00
## trait_typesurvival:warm_coldcold:scalegen_selection         -0.80     0.59 1.00
## trait_typebody_size:warm_coldwarm:scalegen_selection        -0.18     0.10 1.00
## trait_typefecundity:warm_coldwarm:scalegen_selection        -0.41     0.15 1.00
## trait_typesurvival:warm_coldwarm:scalegen_selection         -0.66     0.76 1.00
## trait_typebody_size:warm_coldcold:scalegen_common_garden    -1.27     1.18 1.00
## trait_typefecundity:warm_coldcold:scalegen_common_garden    -1.27     2.88 1.00
## trait_typesurvival:warm_coldcold:scalegen_common_garden     -2.63     2.33 1.00
## trait_typebody_size:warm_coldwarm:scalegen_common_garden    -1.06     0.73 1.00
## trait_typefecundity:warm_coldwarm:scalegen_common_garden    -0.06     0.08 1.00
## trait_typesurvival:warm_coldwarm:scalegen_common_garden     -1.46     1.48 1.00
##                                                          Bulk_ESS Tail_ESS
## trait_typebody_size:warm_coldcold                            4092     4735
## trait_typefecundity:warm_coldcold                            4850     5708
## trait_typesurvival:warm_coldcold                             4449     4672
## trait_typebody_size:warm_coldwarm                            3184     3857
## trait_typefecundity:warm_coldwarm                            3037     4024
## trait_typesurvival:warm_coldwarm                             4051     4019
## trait_typebody_size:warm_coldcold:assay_temp_diff            3053     4705
## trait_typefecundity:warm_coldcold:assay_temp_diff            5182     5436
## trait_typesurvival:warm_coldcold:assay_temp_diff             4312     5069
## trait_typebody_size:warm_coldwarm:assay_temp_diff            3133     4641
## trait_typefecundity:warm_coldwarm:assay_temp_diff            3229     4879
## trait_typesurvival:warm_coldwarm:assay_temp_diff             4695     5673
## trait_typebody_size:warm_coldcold:scaleselect_temp_diff      3511     4810
## trait_typefecundity:warm_coldcold:scaleselect_temp_diff      5220     5138
## trait_typesurvival:warm_coldcold:scaleselect_temp_diff       4013     4371
## trait_typebody_size:warm_coldwarm:scaleselect_temp_diff      3665     5246
## trait_typefecundity:warm_coldwarm:scaleselect_temp_diff      2875     4836
## trait_typesurvival:warm_coldwarm:scaleselect_temp_diff       4256     4342
## trait_typebody_size:warm_coldcold:scalegen_selection         3945     5379
## trait_typefecundity:warm_coldcold:scalegen_selection         5406     6015
## trait_typesurvival:warm_coldcold:scalegen_selection          4241     4808
## trait_typebody_size:warm_coldwarm:scalegen_selection         4182     5575
## trait_typefecundity:warm_coldwarm:scalegen_selection         2750     4380
## trait_typesurvival:warm_coldwarm:scalegen_selection          4376     4436
## trait_typebody_size:warm_coldcold:scalegen_common_garden     4993     5306
## trait_typefecundity:warm_coldcold:scalegen_common_garden     6715     5756
## trait_typesurvival:warm_coldcold:scalegen_common_garden      4269     5049
## trait_typebody_size:warm_coldwarm:scalegen_common_garden     4005     5288
## trait_typefecundity:warm_coldwarm:scalegen_common_garden     5139     5533
## trait_typesurvival:warm_coldwarm:scalegen_common_garden      5471     5371
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnVR_model_all_moderators, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((cold|warm)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter),
    # Remove "scale" from all moderator variables
    Parameter = gsub("scale", "", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) -0.083 -0.381 0.231
fecundity(cold) -0.281 -0.882 0.314
survival(cold) 0.112 -0.845 1.094
body_size(warm) -0.036 -0.288 0.230
fecundity(warm) -0.228 -0.491 0.028
survival(warm) 0.222 -0.189 0.669
body_size(cold):assay_temp_diff 0.000 -0.062 0.062
fecundity(cold):assay_temp_diff -0.198 -0.300 -0.093
survival(cold):assay_temp_diff -0.018 -0.113 0.080
body_size(warm):assay_temp_diff 0.016 -0.028 0.061
fecundity(warm):assay_temp_diff 0.033 -0.002 0.069
survival(warm):assay_temp_diff -0.026 -0.079 0.029
body_size(cold):select_temp_diff 0.092 -0.251 0.435
fecundity(cold):select_temp_diff -0.149 -0.716 0.438
survival(cold):select_temp_diff -0.033 -1.761 1.613
body_size(warm):select_temp_diff -0.175 -0.377 0.028
fecundity(warm):select_temp_diff -0.108 -0.334 0.114
survival(warm):select_temp_diff 0.008 -0.290 0.276
body_size(cold):gen_selection 0.070 -0.172 0.307
fecundity(cold):gen_selection -0.075 -0.415 0.264
survival(cold):gen_selection -0.112 -0.800 0.589
body_size(warm):gen_selection -0.041 -0.179 0.104
fecundity(warm):gen_selection -0.131 -0.413 0.146
survival(warm):gen_selection 0.033 -0.663 0.756
body_size(cold):gen_common_garden -0.048 -1.269 1.184
fecundity(cold):gen_common_garden 0.781 -1.271 2.883
survival(cold):gen_common_garden -0.181 -2.627 2.330
body_size(warm):gen_common_garden -0.167 -1.056 0.735
fecundity(warm):gen_common_garden 0.009 -0.065 0.083
survival(warm):gen_common_garden 0.008 -1.465 1.478
# Generate predicted values at different assay temperatures
emmeans_full_model <- as.data.frame(emmeans(
  lnVR_model_all_moderators,
  specs = ~ assay_temp_diff * select_temp_diff * gen_selection * gen_common_garden | trait_type * warm_cold,
  at = list(assay_temp_diff = c(-8.5, -4, 0, 4, 5, -5, 17, 20)) # Predict at unique min, control, max values
))

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_assay = min(assay_temp_diff),
    max_assay = max(assay_temp_diff),
    control_assay = 0
  )

emmeans_full_model$trait_type <- factor(emmeans_full_model$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_full_model$warm_cold <- factor(emmeans_full_model$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_full_model %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    assay_temp_diff == min_assay |
    assay_temp_diff == max_assay |
    assay_temp_diff == control_assay) %>% 
    dplyr::select(-min_assay, -max_assay, -control_assay) %>% 
    mutate(percentage_change = (exp(emmean) - 1) * 100,
           percentage_lower_HPD = (exp(lower.HPD) - 1) * 100,
           percentage_upper_HPD = (exp(upper.HPD) - 1) * 100) %>%
  mutate(across(c(emmean, 
                  lower.HPD, 
                  upper.HPD, 
                  percentage_change,
                  percentage_lower_HPD, 
                  percentage_upper_HPD), ~ round(., 3))) %>%   # Round numbers to 3 decimal points
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
assay_temp_diff select_temp_diff gen_selection gen_common_garden trait_type warm_cold emmean lower.HPD upper.HPD percentage_change percentage_lower_HPD percentage_upper_HPD
-8.5 5.64645 29.0084 2.710084 Body size Cold -0.078 -0.650 0.552 -7.491 -47.773 73.668
0.0 5.64645 29.0084 2.710084 Body size Cold -0.085 -0.392 0.216 -8.108 -32.460 24.050
5.0 5.64645 29.0084 2.710084 Body size Cold -0.087 -0.536 0.345 -8.315 -41.511 41.148
-8.5 5.64645 29.0084 2.710084 Fecundity Cold 1.413 0.302 2.480 310.635 35.251 1094.609
0.0 5.64645 29.0084 2.710084 Fecundity Cold -0.280 -0.865 0.324 -24.434 -57.915 38.311
5.0 5.64645 29.0084 2.710084 Fecundity Cold -1.275 -2.009 -0.482 -72.052 -86.592 -38.222
-8.5 5.64645 29.0084 2.710084 Survival Cold 0.258 -1.001 1.374 29.383 -63.251 294.925
0.0 5.64645 29.0084 2.710084 Survival Cold 0.108 -0.818 1.107 11.434 -55.875 202.606
4.0 5.64645 29.0084 2.710084 Survival Cold 0.034 -1.058 1.090 3.435 -65.279 197.415
0.0 5.64645 29.0084 2.710084 Body size Warm -0.038 -0.288 0.230 -3.732 -25.040 25.816
-5.0 5.64645 29.0084 2.710084 Body size Warm -0.116 -0.524 0.296 -10.944 -40.778 34.449
17.0 5.64645 29.0084 2.710084 Body size Warm 0.232 -0.426 0.930 26.127 -34.677 153.410
-4.0 5.64645 29.0084 2.710084 Fecundity Warm -0.359 -0.706 0.002 -30.160 -50.615 0.224
0.0 5.64645 29.0084 2.710084 Fecundity Warm -0.227 -0.494 0.024 -20.270 -38.967 2.465
20.0 5.64645 29.0084 2.710084 Fecundity Warm 0.429 -0.198 0.999 53.496 -17.938 171.680
0.0 5.64645 29.0084 2.710084 Survival Warm 0.216 -0.216 0.639 24.172 -19.460 89.382
-5.0 5.64645 29.0084 2.710084 Survival Warm 0.348 -0.204 0.907 41.687 -18.484 147.766
17.0 5.64645 29.0084 2.710084 Survival Warm -0.230 -1.087 0.704 -20.537 -66.292 102.194

Data visualisation

Marginal means

# Generate predictions at assay_temp_diff = 0, or 5 degrees below or above the control temperatures
emmeans_full_model <- as.data.frame(emmeans(
  lnVR_model_all_moderators,
  specs = ~ assay_temp_diff * select_temp_diff * gen_selection * gen_common_garden | trait_type * warm_cold,
  at = list(assay_temp_diff = c(-5, 0, 5) # Re-acclimated to control, or 5 degrees above/below the contol
  ))) # 2 generations of common garden

# Rename variable levels
emmeans_full_model$trait_type <- factor(emmeans_full_model$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_full_model$warm_cold <- factor(emmeans_full_model$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))
emmeans_full_model
##    assay_temp_diff select_temp_diff gen_selection gen_common_garden trait_type
## 1               -5          5.64645       29.0084          2.710084  Body size
## 2                0          5.64645       29.0084          2.710084  Body size
## 3                5          5.64645       29.0084          2.710084  Body size
## 4               -5          5.64645       29.0084          2.710084  Fecundity
## 5                0          5.64645       29.0084          2.710084  Fecundity
## 6                5          5.64645       29.0084          2.710084  Fecundity
## 7               -5          5.64645       29.0084          2.710084   Survival
## 8                0          5.64645       29.0084          2.710084   Survival
## 9                5          5.64645       29.0084          2.710084   Survival
## 10              -5          5.64645       29.0084          2.710084  Body size
## 11               0          5.64645       29.0084          2.710084  Body size
## 12               5          5.64645       29.0084          2.710084  Body size
## 13              -5          5.64645       29.0084          2.710084  Fecundity
## 14               0          5.64645       29.0084          2.710084  Fecundity
## 15               5          5.64645       29.0084          2.710084  Fecundity
## 16              -5          5.64645       29.0084          2.710084   Survival
## 17               0          5.64645       29.0084          2.710084   Survival
## 18               5          5.64645       29.0084          2.710084   Survival
##    warm_cold      emmean  lower.HPD   upper.HPD
## 1       Cold -0.08064238 -0.4995174  0.35636726
## 2       Cold -0.08455378 -0.3924526  0.21551387
## 3       Cold -0.08680692 -0.5363397  0.34463802
## 4       Cold  0.71680891 -0.1019656  1.53187570
## 5       Cold -0.28016725 -0.8654796  0.32433172
## 6       Cold -1.27480792 -2.0093152 -0.48161845
## 7       Cold  0.19700463 -0.8468015  1.19837676
## 8       Cold  0.10826501 -0.8181482  1.10726151
## 9       Cold  0.01652157 -1.0856681  1.15063228
## 10      Warm -0.11590848 -0.5238690  0.29601598
## 11      Warm -0.03803553 -0.2882221  0.22964953
## 12      Warm  0.04308212 -0.1989313  0.30604115
## 13      Warm -0.39198484 -0.7850204 -0.02030154
## 14      Warm -0.22652041 -0.4937523  0.02435364
## 15      Warm -0.06490229 -0.2884375  0.16238805
## 16      Warm  0.34845267 -0.2043654  0.90731380
## 17      Warm  0.21649458 -0.2164120  0.63859658
## 18      Warm  0.08608553 -0.3347825  0.53397689
# Plot
ggplot() +
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75, 
               lwd=1) +
    geom_quasirandom(data = data,     # Plot effect sizes, scaled by precision
                     aes(x = trait_type:warm_cold, 
                         y = lnVR, 
                         fill = trait_type:warm_cold, 
                         size = 1/sqrt(var_lnVR)), 
                     color = "black",
                     shape = 21,
                     width = 0.3, 
                     alpha = 0.3) +
    geom_errorbar(data = filter(emmeans_full_model,
                                assay_temp_diff == "-5"),  # 5 degrees below control (background)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="white",
                  size = 2.75,
                  width = 0.16,
               position = position_nudge(x=-0.25)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "-5"),  # 5 degrees below control (background)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 21,
               size = 4.5, 
               stroke = 2,
               color="white",
               fill = "white",
               position = position_nudge(x=-0.25)) +
    geom_errorbar(data = filter(emmeans_full_model,
                             assay_temp_diff == "-5"), # 5 degrees below control (credible intervals)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="#06B4BA",
                  size = 2,
                  width = 0.12,
               position = position_nudge(x=-0.25)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "-5"), # 5 degrees below control  (point estimates)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 21,
               size = 3.5, 
               stroke = 2,
               color="#06B4BA",
               fill = "white",
               position = position_nudge(x=-0.25)) +

      geom_errorbar(data = filter(emmeans_full_model,
                                assay_temp_diff == "0"),  # control temperature (background)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="white",
                  size = 2.75,
                  width = 0.16,
               position = position_nudge(x=0)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "0"),  # control temperature (background)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 22,
               size = 4.5, 
               stroke = 2,
               color="white",
               fill = "white",
               position = position_nudge(x=0)) +
    geom_errorbar(data = filter(emmeans_full_model,
                             assay_temp_diff == "0"), # control temperature (credible intervals)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="black",
                  size = 2,
                  width = 0.12,
               position = position_nudge(x=0)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "0"), # control temperature (point estimates)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 22,
               size = 3.5, 
               stroke = 2,
               color="black",
               fill = "white",
               position = position_nudge(x=0)) +
  
      geom_errorbar(data = filter(emmeans_full_model,
                                assay_temp_diff == "5"),  # 5 degrees above control (background)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="white",
                  size = 2.75,
                  width = 0.16,
               position = position_nudge(x=0.25)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "5"),  # 5 degrees above control (background)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 23,
               size = 4.5, 
               stroke = 2,
               color="white",
               fill = "white",
               position = position_nudge(x=0.25)) +
    geom_errorbar(data = filter(emmeans_full_model,
                             assay_temp_diff == "5"), # 5 degrees above control (credible intervals)
                  aes(x = trait_type:warm_cold, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="#E80756",
                  size = 2,
                  width = 0.12,
               position = position_nudge(x=0.25)) +
    geom_point(data = filter(emmeans_full_model,
                             assay_temp_diff == "5"), # 5 degrees above control (point estimates)
               aes(x = trait_type:warm_cold, 
                   y = emmean),
               shape = 23,
               size = 3.5, 
               stroke = 2,
               color="#E80756",
               fill = "white",
               position = position_nudge(x=0.25)) +
  
    geom_text(data = sample_sizes,  # Sample size annotations 
              aes(x = trait_type:warm_cold, 
                  y = 3,
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1, size = 5, show.legend = FALSE) +
  
    theme_bw() +     # Customize the plot
    labs(y = "lnVR", x = "") +
    scale_size_continuous(range = c(2, 8))+ 
    scale_fill_manual(values = c("#06B4BA", "#E80756", "#06B4BA", "#E80756", "#06B4BA", "#E80756"))+
    scale_color_manual(values = c("Cold" = "#06B4BA", "Warm" = "#E80756")) +  # Text colour
    theme(text = element_text(size = 20, color = "black"),
          legend.title = ggplot2::element_text(size = 16),
          legend.text = ggplot2::element_text(size = 14),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
          panel.border = element_rect(color = "black", size = 1.5)) +
    guides(fill = "none", size = "none")+
    coord_flip() + 
    ylim(-3.5, 3.5)

ggsave(file = "fig/lnVR_all_moderators_marginal_means.png", width = 12, height = 8, dpi = 500)

Overall trend with assay temperature

# Generate predictions for all assay temperatures
emmeans_full_model_assay <- as.data.frame(emmeans(
  lnVR_model_all_moderators,
  specs = ~ assay_temp_diff * select_temp_diff * gen_selection * gen_common_garden | trait_type * warm_cold,
  at = list(assay_temp_diff = seq(min(data$assay_temp_diff), max(data$assay_temp_diff), by = 0.5) # Re-acclimated to control, or 5 degrees above/below the contol
  ))) 


# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_assay_temp_diff = min(assay_temp_diff),
    max_assay_temp_diff = max(assay_temp_diff)
  )

# Rename variable levels
emmeans_full_model_assay$trait_type <- factor(emmeans_full_model_assay$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_full_model_assay$warm_cold <- factor(emmeans_full_model_assay$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_full_model_assay <- emmeans_full_model_assay %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    assay_temp_diff >= min_assay_temp_diff,
    assay_temp_diff <= max_assay_temp_diff
  )


# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) +  
    geom_vline(xintercept = 0, # Vertical line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data, # Effect sizes, scaled by precision
                  aes(x = assay_temp_diff, 
                      y = lnVR, 
                      size = 1/sqrt(var_lnVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_full_model_assay, # Shaded area for credible intervals
                 aes(x = assay_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_full_model_assay,  # Predicted regression line
               aes(y = emmean,
                   x = assay_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) + 
  
    geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  
  facet_wrap(~ trait_type, ncol = 1) + # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Assay temperature difference", y = "lnVR",
       col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3.5, 3.5))

ggsave(file = "fig/lnVR_all_moderators_assay_temp_diff.png", width = 12, height = 10, dpi = 500)

Publication bias

Changes in mean responses (lnRR)

Egger’s regression

Model specification

# Model specification
formula <- bf(lnRR ~ 0 + trait_type:warm_cold + 
                         trait_type:warm_cold:assay_temp_diff + 
                         trait_type:warm_cold:var_lnRR + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnRR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnRR_model_pub_bias_var <- brm(formula, 
                                            family = gaussian(),
                                            data = data, 
                                            data2 = list(phylo_matrix = phylo_matrix,
                                                         VCV_lnRR = VCV_lnRR),
                                            prior = prior,
                                            control = list(adapt_delta = 0.99, max_treedepth = 15),
                                            iter = 4000, 
                                            warmup = 2000,
                                            chains = 4, 
                                            cores = 4, 
                                            seed = 123) 
# Save model
saveRDS(lnRR_model_pub_bias_var, file = "RData/lnRR_model_pub_bias_var.rds")

Model output

# Load model
lnRR_model_pub_bias_var <- readRDS("RData/lnRR_model_pub_bias_var.rds")

# Display model output
summary(lnRR_model_pub_bias_var)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnRR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:var_lnRR + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnRR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.01      625      928
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.05      0.00     0.04     0.06 1.00     1762     3592
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.03      0.02     0.00     0.07 1.00     1805     3058
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.01      0.01     0.00
## sd(trait_typefecundity)                          0.21      0.04     0.15
## sd(trait_typesurvival)                           0.13      0.03     0.07
## cor(trait_typebody_size,trait_typefecundity)    -0.18      0.46    -0.92
## cor(trait_typebody_size,trait_typesurvival)      0.02      0.49    -0.86
## cor(trait_typefecundity,trait_typesurvival)     -0.23      0.50    -0.94
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.03 1.00     1307     2565
## sd(trait_typefecundity)                          0.29 1.00     3203     5556
## sd(trait_typesurvival)                           0.20 1.00     3705     5525
## cor(trait_typebody_size,trait_typefecundity)     0.77 1.02      244      684
## cor(trait_typebody_size,trait_typesurvival)      0.88 1.01      789     2165
## cor(trait_typefecundity,trait_typesurvival)      0.77 1.00      970     2410
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.05 1.00     1987     3132
## 
## Regression Coefficients:
##                                                   Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                     0.03      0.02    -0.01
## trait_typefecundity:warm_coldcold                    -0.30      0.08    -0.46
## trait_typesurvival:warm_coldcold                     -0.09      0.07    -0.22
## trait_typebody_size:warm_coldwarm                     0.00      0.02    -0.04
## trait_typefecundity:warm_coldwarm                    -0.04      0.05    -0.13
## trait_typesurvival:warm_coldwarm                     -0.02      0.04    -0.10
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.00      0.00    -0.00
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.07      0.01    -0.08
## trait_typesurvival:warm_coldcold:assay_temp_diff     -0.04      0.00    -0.05
## trait_typebody_size:warm_coldwarm:assay_temp_diff    -0.00      0.00    -0.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.00      0.00    -0.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.00      0.00    -0.00
## trait_typebody_size:warm_coldcold:var_lnRR          -37.45     16.09   -69.80
## trait_typefecundity:warm_coldcold:var_lnRR            9.26      3.29     2.90
## trait_typesurvival:warm_coldcold:var_lnRR             2.89      4.72    -6.48
## trait_typebody_size:warm_coldwarm:var_lnRR           -6.01      3.50   -12.92
## trait_typefecundity:warm_coldwarm:var_lnRR            0.20      0.18    -0.16
## trait_typesurvival:warm_coldwarm:var_lnRR             0.57      0.46    -0.33
##                                                   u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                     0.08 1.00     2091
## trait_typefecundity:warm_coldcold                    -0.14 1.00     3390
## trait_typesurvival:warm_coldcold                      0.06 1.00     3209
## trait_typebody_size:warm_coldwarm                     0.05 1.00     2441
## trait_typefecundity:warm_coldwarm                     0.05 1.00     2745
## trait_typesurvival:warm_coldwarm                      0.06 1.00     3477
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.01 1.00     1674
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.06 1.00     4928
## trait_typesurvival:warm_coldcold:assay_temp_diff     -0.03 1.00     3469
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.00 1.00     3007
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.01 1.00     3512
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.01 1.00     5080
## trait_typebody_size:warm_coldcold:var_lnRR           -6.12 1.00     3459
## trait_typefecundity:warm_coldcold:var_lnRR           15.76 1.00     6363
## trait_typesurvival:warm_coldcold:var_lnRR            12.23 1.00     5556
## trait_typebody_size:warm_coldwarm:var_lnRR            0.80 1.00     7407
## trait_typefecundity:warm_coldwarm:var_lnRR            0.56 1.00    11077
## trait_typesurvival:warm_coldwarm:var_lnRR             1.47 1.00    10992
##                                                   Tail_ESS
## trait_typebody_size:warm_coldcold                     2920
## trait_typefecundity:warm_coldcold                     4988
## trait_typesurvival:warm_coldcold                      4578
## trait_typebody_size:warm_coldwarm                     2755
## trait_typefecundity:warm_coldwarm                     3995
## trait_typesurvival:warm_coldwarm                      4608
## trait_typebody_size:warm_coldcold:assay_temp_diff     3045
## trait_typefecundity:warm_coldcold:assay_temp_diff     6254
## trait_typesurvival:warm_coldcold:assay_temp_diff      4987
## trait_typebody_size:warm_coldwarm:assay_temp_diff     4786
## trait_typefecundity:warm_coldwarm:assay_temp_diff     5052
## trait_typesurvival:warm_coldwarm:assay_temp_diff      5221
## trait_typebody_size:warm_coldcold:var_lnRR            5560
## trait_typefecundity:warm_coldcold:var_lnRR            6420
## trait_typesurvival:warm_coldcold:var_lnRR             5414
## trait_typebody_size:warm_coldwarm:var_lnRR            6098
## trait_typefecundity:warm_coldwarm:var_lnRR            6408
## trait_typesurvival:warm_coldwarm:var_lnRR             6471
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnRR_model_pub_bias_var, summary = TRUE)) %>%
    # Rename categorical variables for cleaner display
rownames_to_column(var = "Parameter") %>%
    mutate(Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)",
        Parameter), Parameter = gsub("trait_type([a-z_]+)\\(warm\\):assay_temp_diff",
        "\\1(warm): assay_temp_diff", Parameter)) %>%
    # Round numbers to 3 decimal points
mutate(across(c(Estimate, Q2.5, Q97.5), ~round(., 3))) %>%
    select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
    kable() %>%
    kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE) %>%
    row_spec(0, background = "white", color = "black", bold = TRUE) %>%
    kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) 0.034 -0.013 0.082
fecundity(cold) -0.298 -0.456 -0.143
survival(cold) -0.087 -0.222 0.058
body_size(warm) 0.003 -0.043 0.048
fecundity(warm) -0.040 -0.133 0.055
survival(warm) -0.019 -0.096 0.058
body_size(cold):assay_temp_diff 0.001 -0.003 0.006
fecundity(cold):assay_temp_diff -0.066 -0.076 -0.055
survival(cold):assay_temp_diff -0.045 -0.054 -0.035
body_size(warm):assay_temp_diff -0.001 -0.004 0.003
fecundity(warm):assay_temp_diff 0.004 -0.003 0.012
survival(warm):assay_temp_diff 0.005 -0.002 0.011
body_size(cold):var_lnRR -37.450 -69.801 -6.116
fecundity(cold):var_lnRR 9.258 2.897 15.765
survival(cold):var_lnRR 2.893 -6.477 12.231
body_size(warm):var_lnRR -6.010 -12.925 0.805
fecundity(warm):var_lnRR 0.204 -0.161 0.562
survival(warm):var_lnRR 0.575 -0.330 1.468

Data visualisation

# Generate predictions
emmeans_pub_bias_var <- as.data.frame(emmeans(
  lnRR_model_pub_bias_var,
  specs = ~ var_lnRR | trait_type * warm_cold,
  at = list(var_lnRR = seq(0, max(data$var_lnRR), by = 0.1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

emmeans_pub_bias_var$trait_type <- factor(emmeans_pub_bias_var$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_pub_bias_var$warm_cold <- factor(emmeans_pub_bias_var$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = var_lnRR, 
                      y = lnRR, 
                      size = 1/sqrt(var_lnRR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.001)) + 
     geom_ribbon(data = emmeans_pub_bias_var, # Shaded area for credible intervals
                 aes(x = var_lnRR,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_pub_bias_var, # Predicted regression line
               aes(y = emmean,
                   x = var_lnRR,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -0.8, -1.3),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Sampling variance of lnRR", y = "lnRR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-1.5, 1.5), xlim = c(0, 0.3))

ggsave(file = "fig/lnRR_pub_bias_var.png", width = 12, height = 7, dpi = 500)

Publication year

Model specification

# Model specification
formula <- bf(lnRR ~ 0 + trait_type:warm_cold + 
                         trait_type:warm_cold:assay_temp_diff + 
                         trait_type:warm_cold:scale(pub_year) + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnRR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnRR_model_pub_bias_year <- brm(formula, 
                                            family = gaussian(),
                                            data = data, 
                                            data2 = list(phylo_matrix = phylo_matrix,
                                                         VCV_lnRR = VCV_lnRR),
                                            prior = prior,
                                            control = list(adapt_delta = 0.99, max_treedepth = 15),
                                            iter = 4000, 
                                            warmup = 2000,
                                            chains = 4, 
                                            cores = 4, 
                                            seed = 123) 
# Save model
saveRDS(lnRR_model_pub_bias_year, file = "RData/lnRR_model_pub_bias_year.rds")

Model output

# Load model
lnRR_model_pub_bias_year <- readRDS("RData/lnRR_model_pub_bias_year.rds")

# Display model output 
summary(lnRR_model_pub_bias_year)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnRR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:scale(pub_year) + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnRR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.01      636      935
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.05      0.00     0.04     0.06 1.00     1762     2828
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.02     0.00     0.06 1.00     2547     3963
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.01      0.01     0.00
## sd(trait_typefecundity)                          0.20      0.04     0.14
## sd(trait_typesurvival)                           0.12      0.03     0.07
## cor(trait_typebody_size,trait_typefecundity)    -0.09      0.48    -0.88
## cor(trait_typebody_size,trait_typesurvival)      0.09      0.49    -0.83
## cor(trait_typefecundity,trait_typesurvival)     -0.17      0.48    -0.93
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.03 1.00     1842     3407
## sd(trait_typefecundity)                          0.28 1.00     3405     5116
## sd(trait_typesurvival)                           0.19 1.00     3689     5281
## cor(trait_typebody_size,trait_typefecundity)     0.82 1.01      457     1387
## cor(trait_typebody_size,trait_typesurvival)      0.89 1.01      928     2233
## cor(trait_typefecundity,trait_typesurvival)      0.73 1.00     1472     3245
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.00     2734     4675
## 
## Regression Coefficients:
##                                                   Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                     0.01      0.02    -0.03
## trait_typefecundity:warm_coldcold                    -0.10      0.07    -0.23
## trait_typesurvival:warm_coldcold                     -0.01      0.08    -0.16
## trait_typebody_size:warm_coldwarm                    -0.00      0.02    -0.05
## trait_typefecundity:warm_coldwarm                    -0.03      0.05    -0.12
## trait_typesurvival:warm_coldwarm                     -0.02      0.04    -0.09
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.00      0.00    -0.00
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.06      0.01    -0.07
## trait_typesurvival:warm_coldcold:assay_temp_diff     -0.04      0.00    -0.05
## trait_typebody_size:warm_coldwarm:assay_temp_diff    -0.00      0.00    -0.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.00      0.00    -0.00
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.00      0.00    -0.00
## trait_typebody_size:warm_coldcold:scalepub_year      -0.01      0.01    -0.03
## trait_typefecundity:warm_coldcold:scalepub_year       0.16      0.05     0.06
## trait_typesurvival:warm_coldcold:scalepub_year        0.06      0.06    -0.05
## trait_typebody_size:warm_coldwarm:scalepub_year       0.01      0.01    -0.01
## trait_typefecundity:warm_coldwarm:scalepub_year       0.04      0.04    -0.04
## trait_typesurvival:warm_coldwarm:scalepub_year        0.04      0.04    -0.03
##                                                   u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                     0.06 1.00     2334
## trait_typefecundity:warm_coldcold                     0.03 1.00     5017
## trait_typesurvival:warm_coldcold                      0.15 1.00     5895
## trait_typebody_size:warm_coldwarm                     0.04 1.00     2820
## trait_typefecundity:warm_coldwarm                     0.06 1.00     4453
## trait_typesurvival:warm_coldwarm                      0.07 1.00     4478
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.01 1.00     2291
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.05 1.00     4921
## trait_typesurvival:warm_coldcold:assay_temp_diff     -0.04 1.00     3913
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.00 1.00     3929
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.01 1.00     3076
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.01 1.00     6488
## trait_typebody_size:warm_coldcold:scalepub_year       0.01 1.00     2230
## trait_typefecundity:warm_coldcold:scalepub_year       0.26 1.00     4980
## trait_typesurvival:warm_coldcold:scalepub_year        0.17 1.00     4804
## trait_typebody_size:warm_coldwarm:scalepub_year       0.03 1.00     3189
## trait_typefecundity:warm_coldwarm:scalepub_year       0.12 1.00     4032
## trait_typesurvival:warm_coldwarm:scalepub_year        0.12 1.00     4954
##                                                   Tail_ESS
## trait_typebody_size:warm_coldcold                     2788
## trait_typefecundity:warm_coldcold                     5695
## trait_typesurvival:warm_coldcold                      6214
## trait_typebody_size:warm_coldwarm                     2872
## trait_typefecundity:warm_coldwarm                     4859
## trait_typesurvival:warm_coldwarm                      5133
## trait_typebody_size:warm_coldcold:assay_temp_diff     4090
## trait_typefecundity:warm_coldcold:assay_temp_diff     6315
## trait_typesurvival:warm_coldcold:assay_temp_diff      6167
## trait_typebody_size:warm_coldwarm:assay_temp_diff     4832
## trait_typefecundity:warm_coldwarm:assay_temp_diff     5716
## trait_typesurvival:warm_coldwarm:assay_temp_diff      5181
## trait_typebody_size:warm_coldcold:scalepub_year       3673
## trait_typefecundity:warm_coldcold:scalepub_year       5820
## trait_typesurvival:warm_coldcold:scalepub_year        5389
## trait_typebody_size:warm_coldwarm:scalepub_year       4412
## trait_typefecundity:warm_coldwarm:scalepub_year       4828
## trait_typesurvival:warm_coldwarm:scalepub_year        5519
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnRR_model_pub_bias_year, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((cold|warm)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter),
    # Remove "scale" from pub_year
    Parameter = gsub("scalepub_year", "pub_year", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) 0.011 -0.035 0.056
fecundity(cold) -0.096 -0.231 0.032
survival(cold) -0.007 -0.164 0.152
body_size(warm) -0.005 -0.049 0.036
fecundity(warm) -0.032 -0.124 0.059
survival(warm) -0.016 -0.093 0.066
body_size(cold):assay_temp_diff 0.002 -0.003 0.007
fecundity(cold):assay_temp_diff -0.063 -0.074 -0.053
survival(cold):assay_temp_diff -0.045 -0.054 -0.035
body_size(warm):assay_temp_diff -0.001 -0.004 0.002
fecundity(warm):assay_temp_diff 0.004 -0.003 0.011
survival(warm):assay_temp_diff 0.005 -0.002 0.011
body_size(cold):pub_year -0.008 -0.030 0.013
fecundity(cold):pub_year 0.157 0.062 0.256
survival(cold):pub_year 0.063 -0.054 0.175
body_size(warm):pub_year 0.006 -0.015 0.026
fecundity(warm):pub_year 0.038 -0.039 0.119
survival(warm):pub_year 0.042 -0.033 0.117

Data visualisation

# Generate predictions
emmeans_pub_bias_year <- as.data.frame(emmeans(
  lnRR_model_pub_bias_year,
  specs = ~ pub_year | trait_type * warm_cold,
  at = list(pub_year = seq(min(data$pub_year), max(data$pub_year), by = 1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_pub_year = min(pub_year),
    max_pub_year = max(pub_year)
  )

emmeans_pub_bias_year$trait_type <- factor(emmeans_pub_bias_year$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_pub_bias_year$warm_cold <- factor(emmeans_pub_bias_year$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_pub_bias_year <- emmeans_pub_bias_year %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    pub_year >= min_pub_year,
    pub_year <= max_pub_year
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = pub_year, 
                      y = lnRR, 
                      size = 1/sqrt(pub_year), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_pub_bias_year, # Shaded area for credible intervals
                 aes(x = pub_year,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_pub_bias_year, # Predicted regression line
               aes(y = emmean,
                   x = pub_year,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -0.9, -1.3),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Sampling variance of lnRR", y = "lnRR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none") + 
    coord_cartesian(ylim = c(-1.5, 1.5))

ggsave(file = "fig/lnRR_pub_bias_year.png", width = 12, height = 7, dpi = 500)

Changes in relative trait variance (lnCVR)

Egger’s regression

Model specification

# Model specification
formula <- bf(lnCVR ~ 0 + trait_type:warm_cold + 
                         trait_type:warm_cold:assay_temp_diff + 
                         trait_type:warm_cold:var_lnCVR + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnCVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnCVR_model_pub_bias_var <- brm(formula, 
                                            family = gaussian(),
                                            data = data, 
                                            data2 = list(phylo_matrix = phylo_matrix,
                                                         VCV_lnCVR = VCV_lnCVR),
                                            prior = prior,
                                            control = list(adapt_delta = 0.99, max_treedepth = 15),
                                            iter = 4000, 
                                            warmup = 2000,
                                            chains = 4, 
                                            cores = 4, 
                                            seed = 123) 
# Save model
saveRDS(lnCVR_model_pub_bias_var, file = "RData/lnCVR_model_pub_bias_var.rds")

Model output

# Load model
lnCVR_model_pub_bias_var <- readRDS("RData/lnCVR_model_pub_bias_var.rds")

# Display model output
summary(lnCVR_model_pub_bias_var)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnCVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:var_lnCVR + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnCVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.10      0.05     0.01     0.20 1.00     1063     2440
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.39      0.04     0.32     0.47 1.00     1981     3628
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.07     0.00     0.27 1.00     2920     3914
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.06      0.05     0.00
## sd(trait_typefecundity)                          0.11      0.09     0.00
## sd(trait_typesurvival)                           0.56      0.16     0.28
## cor(trait_typebody_size,trait_typefecundity)     0.06      0.49    -0.85
## cor(trait_typebody_size,trait_typesurvival)     -0.01      0.50    -0.86
## cor(trait_typefecundity,trait_typesurvival)     -0.01      0.44    -0.83
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.18 1.00     3284     3493
## sd(trait_typefecundity)                          0.31 1.00     1690     3775
## sd(trait_typesurvival)                           0.92 1.00     2562     3420
## cor(trait_typebody_size,trait_typefecundity)     0.89 1.00     3344     4650
## cor(trait_typebody_size,trait_typesurvival)      0.88 1.00      962     2589
## cor(trait_typefecundity,trait_typesurvival)      0.82 1.00     1421     3139
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.19 1.00     2752     4177
## 
## Regression Coefficients:
##                                                   Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                    -0.07      0.15    -0.36
## trait_typefecundity:warm_coldcold                    -0.06      0.29    -0.63
## trait_typesurvival:warm_coldcold                      0.28      0.83    -1.37
## trait_typebody_size:warm_coldwarm                     0.06      0.11    -0.15
## trait_typefecundity:warm_coldwarm                    -0.05      0.11    -0.25
## trait_typesurvival:warm_coldwarm                      0.25      0.20    -0.13
## trait_typebody_size:warm_coldcold:assay_temp_diff    -0.01      0.02    -0.05
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.15      0.04    -0.23
## trait_typesurvival:warm_coldcold:assay_temp_diff      0.03      0.04    -0.05
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.00      0.02    -0.03
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.02      0.02    -0.01
## trait_typesurvival:warm_coldwarm:assay_temp_diff     -0.02      0.02    -0.07
## trait_typebody_size:warm_coldcold:var_lnCVR           0.29      0.47    -0.63
## trait_typefecundity:warm_coldcold:var_lnCVR          -0.61      0.59    -1.74
## trait_typesurvival:warm_coldcold:var_lnCVR           -0.39      1.80    -3.98
## trait_typebody_size:warm_coldwarm:var_lnCVR          -0.01      0.12    -0.25
## trait_typefecundity:warm_coldwarm:var_lnCVR           0.01      0.03    -0.05
## trait_typesurvival:warm_coldwarm:var_lnCVR           -0.03      0.06    -0.14
##                                                   u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                     0.24 1.00     2396
## trait_typefecundity:warm_coldcold                     0.51 1.00     3133
## trait_typesurvival:warm_coldcold                      1.94 1.00     2648
## trait_typebody_size:warm_coldwarm                     0.29 1.00     2541
## trait_typefecundity:warm_coldwarm                     0.17 1.00     2817
## trait_typesurvival:warm_coldwarm                      0.65 1.00     3752
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.03 1.00     3328
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.07 1.00     5635
## trait_typesurvival:warm_coldcold:assay_temp_diff      0.10 1.00     5175
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.03 1.00     4733
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.05 1.00     4426
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.02 1.00     6333
## trait_typebody_size:warm_coldcold:var_lnCVR           1.22 1.00     3718
## trait_typefecundity:warm_coldcold:var_lnCVR           0.54 1.00     4085
## trait_typesurvival:warm_coldcold:var_lnCVR            3.15 1.00     2748
## trait_typebody_size:warm_coldwarm:var_lnCVR           0.23 1.00     8676
## trait_typefecundity:warm_coldwarm:var_lnCVR           0.06 1.00    11131
## trait_typesurvival:warm_coldwarm:var_lnCVR            0.08 1.00    11184
##                                                   Tail_ESS
## trait_typebody_size:warm_coldcold                     3574
## trait_typefecundity:warm_coldcold                     4664
## trait_typesurvival:warm_coldcold                      3030
## trait_typebody_size:warm_coldwarm                     2873
## trait_typefecundity:warm_coldwarm                     2827
## trait_typesurvival:warm_coldwarm                      4491
## trait_typebody_size:warm_coldcold:assay_temp_diff     4370
## trait_typefecundity:warm_coldcold:assay_temp_diff     5568
## trait_typesurvival:warm_coldcold:assay_temp_diff      5776
## trait_typebody_size:warm_coldwarm:assay_temp_diff     5865
## trait_typefecundity:warm_coldwarm:assay_temp_diff     5656
## trait_typesurvival:warm_coldwarm:assay_temp_diff      5976
## trait_typebody_size:warm_coldcold:var_lnCVR           5437
## trait_typefecundity:warm_coldcold:var_lnCVR           5453
## trait_typesurvival:warm_coldcold:var_lnCVR            3062
## trait_typebody_size:warm_coldwarm:var_lnCVR           5782
## trait_typefecundity:warm_coldwarm:var_lnCVR           5876
## trait_typesurvival:warm_coldwarm:var_lnCVR            5871
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnCVR_model_pub_bias_var, summary = TRUE)) %>%
    # Rename categorical variables for cleaner display
rownames_to_column(var = "Parameter") %>%
    mutate(Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)",
        Parameter), Parameter = gsub("trait_type([a-z_]+)\\(warm\\):assay_temp_diff",
        "\\1(warm): assay_temp_diff", Parameter)) %>%
    # Round numbers to 3 decimal points
mutate(across(c(Estimate, Q2.5, Q97.5), ~round(., 3))) %>%
    select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
    kable() %>%
    kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE) %>%
    row_spec(0, background = "white", color = "black", bold = TRUE) %>%
    kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) -0.068 -0.363 0.238
fecundity(cold) -0.062 -0.628 0.510
survival(cold) 0.283 -1.368 1.937
body_size(warm) 0.062 -0.146 0.293
fecundity(warm) -0.048 -0.255 0.168
survival(warm) 0.250 -0.132 0.652
body_size(cold):assay_temp_diff -0.009 -0.050 0.032
fecundity(cold):assay_temp_diff -0.151 -0.230 -0.071
survival(cold):assay_temp_diff 0.028 -0.049 0.102
body_size(warm):assay_temp_diff 0.002 -0.031 0.035
fecundity(warm):assay_temp_diff 0.017 -0.013 0.048
survival(warm):assay_temp_diff -0.025 -0.073 0.022
body_size(cold):var_lnCVR 0.286 -0.630 1.222
fecundity(cold):var_lnCVR -0.606 -1.744 0.543
survival(cold):var_lnCVR -0.393 -3.976 3.152
body_size(warm):var_lnCVR -0.008 -0.247 0.233
fecundity(warm):var_lnCVR 0.006 -0.046 0.059
survival(warm):var_lnCVR -0.030 -0.143 0.082

Data visualisation

# Generate predictions
emmeans_pub_bias_var <- as.data.frame(emmeans(
  lnCVR_model_pub_bias_var,
  specs = ~ var_lnCVR | trait_type * warm_cold,
  at = list(var_lnCVR = seq(0, max(data$var_lnCVR), by = 1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

emmeans_pub_bias_var$trait_type <- factor(emmeans_pub_bias_var$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_pub_bias_var$warm_cold <- factor(emmeans_pub_bias_var$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = var_lnCVR, 
                      y = lnCVR, 
                      size = 1/sqrt(var_lnCVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.1)) + 
     geom_ribbon(data = emmeans_pub_bias_var, # Shaded area for credible intervals
                 aes(x = var_lnCVR,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_pub_bias_var, # Predicted regression line
               aes(y = emmean,
                   x = var_lnCVR,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -1.9, -2.85),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Sampling variance of lnCVR", y = "lnCVR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none") +
    coord_cartesian(ylim = c(-3.5, 3.5), xlim = c(0, 6))

ggsave(file = "fig/lnCVR_pub_bias_var.png", width = 12, height = 7, dpi = 500)

Publication year

Model specification

# Model specification
formula <- bf(lnCVR ~ 0 + trait_type:warm_cold + 
                         trait_type:warm_cold:assay_temp_diff + 
                         trait_type:warm_cold:scale(pub_year) + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnCVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnCVR_model_pub_bias_year <- brm(formula, 
                                            family = gaussian(),
                                            data = data, 
                                            data2 = list(phylo_matrix = phylo_matrix,
                                                         VCV_lnCVR = VCV_lnCVR),
                                            prior = prior,
                                            control = list(adapt_delta = 0.99, max_treedepth = 15),
                                            iter = 4000, 
                                            warmup = 2000,
                                            chains = 4, 
                                            cores = 4, 
                                            seed = 123) 
# Save model
saveRDS(lnCVR_model_pub_bias_year, file = "RData/lnCVR_model_pub_bias_year.rds")

Model output

# Load model
lnCVR_model_pub_bias_year <- readRDS("RData/lnCVR_model_pub_bias_year.rds")

# Display model output 
summary(lnCVR_model_pub_bias_year)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnCVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:scale(pub_year) + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnCVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.10      0.06     0.01     0.21 1.01     1181     2260
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.40      0.04     0.32     0.48 1.00     2052     4112
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.10      0.08     0.00     0.29 1.00     2668     3221
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.07      0.05     0.00
## sd(trait_typefecundity)                          0.10      0.08     0.00
## sd(trait_typesurvival)                           0.45      0.17     0.11
## cor(trait_typebody_size,trait_typefecundity)     0.02      0.50    -0.87
## cor(trait_typebody_size,trait_typesurvival)     -0.02      0.50    -0.89
## cor(trait_typefecundity,trait_typesurvival)     -0.04      0.47    -0.87
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.20 1.00     3678     4215
## sd(trait_typefecundity)                          0.30 1.00     1983     3752
## sd(trait_typesurvival)                           0.79 1.00     2046     1896
## cor(trait_typebody_size,trait_typefecundity)     0.88 1.00     3875     5140
## cor(trait_typebody_size,trait_typesurvival)      0.87 1.00     1267     2796
## cor(trait_typefecundity,trait_typesurvival)      0.83 1.00     1635     4130
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.07      0.05     0.00     0.20 1.00     3106     4276
## 
## Regression Coefficients:
##                                                   Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                    -0.06      0.13    -0.31
## trait_typefecundity:warm_coldcold                    -0.34      0.23    -0.78
## trait_typesurvival:warm_coldcold                      0.16      0.40    -0.62
## trait_typebody_size:warm_coldwarm                     0.06      0.11    -0.15
## trait_typefecundity:warm_coldwarm                    -0.04      0.11    -0.27
## trait_typesurvival:warm_coldwarm                      0.31      0.18    -0.05
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.00      0.02    -0.04
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.12      0.04    -0.21
## trait_typesurvival:warm_coldcold:assay_temp_diff      0.03      0.04    -0.05
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.00      0.02    -0.03
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.02      0.02    -0.01
## trait_typesurvival:warm_coldwarm:assay_temp_diff     -0.03      0.02    -0.07
## trait_typebody_size:warm_coldcold:scalepub_year      -0.08      0.08    -0.24
## trait_typefecundity:warm_coldcold:scalepub_year      -0.12      0.16    -0.42
## trait_typesurvival:warm_coldcold:scalepub_year       -0.02      0.26    -0.54
## trait_typebody_size:warm_coldwarm:scalepub_year       0.04      0.08    -0.12
## trait_typefecundity:warm_coldwarm:scalepub_year      -0.04      0.10    -0.23
## trait_typesurvival:warm_coldwarm:scalepub_year       -0.32      0.16    -0.63
##                                                   u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                     0.21 1.00     2960
## trait_typefecundity:warm_coldcold                     0.12 1.00     4139
## trait_typesurvival:warm_coldcold                      0.93 1.00     4279
## trait_typebody_size:warm_coldwarm                     0.28 1.00     3128
## trait_typefecundity:warm_coldwarm                     0.18 1.00     3198
## trait_typesurvival:warm_coldwarm                      0.67 1.00     3887
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.04 1.00     2921
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.04 1.00     5240
## trait_typesurvival:warm_coldcold:assay_temp_diff      0.11 1.00     5224
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.04 1.00     4681
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.05 1.00     5046
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.02 1.00     5999
## trait_typebody_size:warm_coldcold:scalepub_year       0.07 1.00     3012
## trait_typefecundity:warm_coldcold:scalepub_year       0.20 1.00     4505
## trait_typesurvival:warm_coldcold:scalepub_year        0.51 1.00     4329
## trait_typebody_size:warm_coldwarm:scalepub_year       0.19 1.00     3249
## trait_typefecundity:warm_coldwarm:scalepub_year       0.16 1.00     4339
## trait_typesurvival:warm_coldwarm:scalepub_year        0.01 1.00     5332
##                                                   Tail_ESS
## trait_typebody_size:warm_coldcold                     4255
## trait_typefecundity:warm_coldcold                     5397
## trait_typesurvival:warm_coldcold                      5604
## trait_typebody_size:warm_coldwarm                     3724
## trait_typefecundity:warm_coldwarm                     3977
## trait_typesurvival:warm_coldwarm                      4586
## trait_typebody_size:warm_coldcold:assay_temp_diff     4436
## trait_typefecundity:warm_coldcold:assay_temp_diff     5979
## trait_typesurvival:warm_coldcold:assay_temp_diff      5692
## trait_typebody_size:warm_coldwarm:assay_temp_diff     5289
## trait_typefecundity:warm_coldwarm:assay_temp_diff     5577
## trait_typesurvival:warm_coldwarm:assay_temp_diff      5578
## trait_typebody_size:warm_coldcold:scalepub_year       4846
## trait_typefecundity:warm_coldcold:scalepub_year       4912
## trait_typesurvival:warm_coldcold:scalepub_year        5491
## trait_typebody_size:warm_coldwarm:scalepub_year       4728
## trait_typefecundity:warm_coldwarm:scalepub_year       5889
## trait_typesurvival:warm_coldwarm:scalepub_year        5242
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnCVR_model_pub_bias_year, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((cold|warm)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter),
    # Remove "scale" from pub_year
    Parameter = gsub("scalepub_year", "pub_year", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) -0.060 -0.308 0.212
fecundity(cold) -0.337 -0.781 0.121
survival(cold) 0.158 -0.621 0.935
body_size(warm) 0.058 -0.151 0.280
fecundity(warm) -0.044 -0.265 0.182
survival(warm) 0.306 -0.052 0.672
body_size(cold):assay_temp_diff 0.001 -0.043 0.044
fecundity(cold):assay_temp_diff -0.125 -0.209 -0.039
survival(cold):assay_temp_diff 0.030 -0.049 0.108
body_size(warm):assay_temp_diff 0.002 -0.030 0.037
fecundity(warm):assay_temp_diff 0.018 -0.013 0.049
survival(warm):assay_temp_diff -0.026 -0.074 0.021
body_size(cold):pub_year -0.083 -0.242 0.073
fecundity(cold):pub_year -0.116 -0.420 0.195
survival(cold):pub_year -0.015 -0.536 0.508
body_size(warm):pub_year 0.038 -0.119 0.193
fecundity(warm):pub_year -0.037 -0.233 0.162
survival(warm):pub_year -0.315 -0.629 0.013

Data visualisation

# Generate predictions
emmeans_pub_bias_year <- as.data.frame(emmeans(
  lnCVR_model_pub_bias_year,
  specs = ~ pub_year | trait_type * warm_cold,
  at = list(pub_year = seq(min(data$pub_year), max(data$pub_year), by = 1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_pub_year = min(pub_year),
    max_pub_year = max(pub_year)
  )

emmeans_pub_bias_year$trait_type <- factor(emmeans_pub_bias_year$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_pub_bias_year$warm_cold <- factor(emmeans_pub_bias_year$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_pub_bias_year <- emmeans_pub_bias_year %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    pub_year >= min_pub_year,
    pub_year <= max_pub_year
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = pub_year, 
                      y = lnCVR, 
                      size = 1/sqrt(pub_year), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_pub_bias_year, # Shaded area for credible intervals
                 aes(x = pub_year,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_pub_bias_year, # Predicted regression line
               aes(y = emmean,
                   x = pub_year,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -1.9, -2.85),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Publication year", y = "lnCVR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none") + 
    coord_cartesian(ylim = c(-3, 3))

ggsave(file = "fig/lnCVR_pub_bias_year.png", width = 12, height = 7, dpi = 500)

Changes in trait variance (lnVR)

Egger’s regression

Model specification

# Model specification
formula <- bf(lnVR ~ 0 + trait_type:warm_cold + 
                         trait_type:warm_cold:assay_temp_diff + 
                         trait_type:warm_cold:var_lnVR + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnVR_model_pub_bias_var <- brm(formula, 
                                            family = gaussian(),
                                            data = data, 
                                            data2 = list(phylo_matrix = phylo_matrix,
                                                         VCV_lnVR = VCV_lnVR),
                                            prior = prior,
                                            control = list(adapt_delta = 0.99, max_treedepth = 15),
                                            iter = 4000, 
                                            warmup = 2000,
                                            chains = 4, 
                                            cores = 4, 
                                            seed = 123) 
# Save model
saveRDS(lnVR_model_pub_bias_var, file = "RData/lnVR_model_pub_bias_var.rds")

Model output

# Load model
lnVR_model_pub_bias_var <- readRDS("RData/lnVR_model_pub_bias_var.rds")

# Display model output
summary(lnVR_model_pub_bias_var)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:var_lnVR + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.06     0.00     0.21 1.01      737     2137
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.68      0.03     0.62     0.75 1.00     2971     5048
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.07     0.00     0.28 1.00     2249     3881
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.07      0.06     0.00
## sd(trait_typefecundity)                          0.08      0.06     0.00
## sd(trait_typesurvival)                           0.29      0.15     0.03
## cor(trait_typebody_size,trait_typefecundity)     0.02      0.50    -0.87
## cor(trait_typebody_size,trait_typesurvival)     -0.04      0.50    -0.89
## cor(trait_typefecundity,trait_typesurvival)     -0.04      0.49    -0.87
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.22 1.00     1908     2981
## sd(trait_typefecundity)                          0.23 1.00     1728     3234
## sd(trait_typesurvival)                           0.60 1.00     1204     1704
## cor(trait_typebody_size,trait_typefecundity)     0.88 1.00     3597     4697
## cor(trait_typebody_size,trait_typesurvival)      0.86 1.00     1327     3062
## cor(trait_typefecundity,trait_typesurvival)      0.86 1.00     1729     3702
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.18 1.00     2962     4612
## 
## Regression Coefficients:
##                                                   Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                    -0.08      0.22    -0.51
## trait_typefecundity:warm_coldcold                    -0.26      0.33    -0.92
## trait_typesurvival:warm_coldcold                      0.02      0.62    -1.22
## trait_typebody_size:warm_coldwarm                     0.04      0.13    -0.21
## trait_typefecundity:warm_coldwarm                    -0.11      0.11    -0.31
## trait_typesurvival:warm_coldwarm                      0.20      0.16    -0.10
## trait_typebody_size:warm_coldcold:assay_temp_diff    -0.02      0.03    -0.08
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.19      0.05    -0.28
## trait_typesurvival:warm_coldcold:assay_temp_diff     -0.01      0.04    -0.10
## trait_typebody_size:warm_coldwarm:assay_temp_diff    -0.00      0.02    -0.04
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.02      0.02    -0.01
## trait_typesurvival:warm_coldwarm:assay_temp_diff     -0.02      0.02    -0.07
## trait_typebody_size:warm_coldcold:var_lnVR            0.39      0.94    -1.41
## trait_typefecundity:warm_coldcold:var_lnVR           -0.56      0.99    -2.48
## trait_typesurvival:warm_coldcold:var_lnVR            -0.25      2.76    -5.59
## trait_typebody_size:warm_coldwarm:var_lnVR            0.02      0.19    -0.36
## trait_typefecundity:warm_coldwarm:var_lnVR            0.00      0.03    -0.05
## trait_typesurvival:warm_coldwarm:var_lnVR            -0.01      0.06    -0.13
##                                                   u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                     0.35 1.00     1542
## trait_typefecundity:warm_coldcold                     0.39 1.00     2623
## trait_typesurvival:warm_coldcold                      1.19 1.00     2402
## trait_typebody_size:warm_coldwarm                     0.30 1.00     2159
## trait_typefecundity:warm_coldwarm                     0.11 1.00     2628
## trait_typesurvival:warm_coldwarm                      0.52 1.00     3041
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.04 1.00     2084
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.09 1.00     3814
## trait_typesurvival:warm_coldcold:assay_temp_diff      0.07 1.00     3404
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.04 1.00     2198
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.05 1.00     2752
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.03 1.00     3352
## trait_typebody_size:warm_coldcold:var_lnVR            2.28 1.00     1942
## trait_typefecundity:warm_coldcold:var_lnVR            1.36 1.00     3364
## trait_typesurvival:warm_coldcold:var_lnVR             5.30 1.00     2714
## trait_typebody_size:warm_coldwarm:var_lnVR            0.40 1.00     5299
## trait_typefecundity:warm_coldwarm:var_lnVR            0.06 1.00     9284
## trait_typesurvival:warm_coldwarm:var_lnVR             0.11 1.00    12933
##                                                   Tail_ESS
## trait_typebody_size:warm_coldcold                     2964
## trait_typefecundity:warm_coldcold                     3808
## trait_typesurvival:warm_coldcold                      2746
## trait_typebody_size:warm_coldwarm                     3478
## trait_typefecundity:warm_coldwarm                     3353
## trait_typesurvival:warm_coldwarm                      4432
## trait_typebody_size:warm_coldcold:assay_temp_diff     3717
## trait_typefecundity:warm_coldcold:assay_temp_diff     5176
## trait_typesurvival:warm_coldcold:assay_temp_diff      4891
## trait_typebody_size:warm_coldwarm:assay_temp_diff     3858
## trait_typefecundity:warm_coldwarm:assay_temp_diff     4295
## trait_typesurvival:warm_coldwarm:assay_temp_diff      4928
## trait_typebody_size:warm_coldcold:var_lnVR            3704
## trait_typefecundity:warm_coldcold:var_lnVR            4765
## trait_typesurvival:warm_coldcold:var_lnVR             3194
## trait_typebody_size:warm_coldwarm:var_lnVR            5165
## trait_typefecundity:warm_coldwarm:var_lnVR            6282
## trait_typesurvival:warm_coldwarm:var_lnVR             6344
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnVR_model_pub_bias_var, summary = TRUE)) %>%
    # Rename categorical variables for cleaner display
rownames_to_column(var = "Parameter") %>%
    mutate(Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)",
        Parameter), Parameter = gsub("trait_type([a-z_]+)\\(warm\\):assay_temp_diff",
        "\\1(warm): assay_temp_diff", Parameter)) %>%
    # Round numbers to 3 decimal points
mutate(across(c(Estimate, Q2.5, Q97.5), ~round(., 3))) %>%
    select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
    kable() %>%
    kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE) %>%
    row_spec(0, background = "white", color = "black", bold = TRUE) %>%
    kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) -0.077 -0.506 0.353
fecundity(cold) -0.263 -0.921 0.391
survival(cold) 0.023 -1.224 1.190
body_size(warm) 0.041 -0.206 0.296
fecundity(warm) -0.106 -0.313 0.115
survival(warm) 0.202 -0.099 0.523
body_size(cold):assay_temp_diff -0.019 -0.076 0.039
fecundity(cold):assay_temp_diff -0.185 -0.283 -0.091
survival(cold):assay_temp_diff -0.014 -0.103 0.074
body_size(warm):assay_temp_diff -0.001 -0.043 0.039
fecundity(warm):assay_temp_diff 0.019 -0.011 0.049
survival(warm):assay_temp_diff -0.022 -0.070 0.026
body_size(cold):var_lnVR 0.395 -1.410 2.278
fecundity(cold):var_lnVR -0.559 -2.477 1.364
survival(cold):var_lnVR -0.249 -5.589 5.301
body_size(warm):var_lnVR 0.016 -0.365 0.396
fecundity(warm):var_lnVR 0.004 -0.053 0.061
survival(warm):var_lnVR -0.011 -0.126 0.107

Data visualisation

# Generate predictions
emmeans_pub_bias_var <- as.data.frame(emmeans(
  lnVR_model_pub_bias_var,
  specs = ~ var_lnVR | trait_type * warm_cold,
  at = list(var_lnVR = seq(0, max(data$var_lnVR), by = 1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

emmeans_pub_bias_var$trait_type <- factor(emmeans_pub_bias_var$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_pub_bias_var$warm_cold <- factor(emmeans_pub_bias_var$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = var_lnVR, 
                      y = lnVR, 
                      size = 1/sqrt(var_lnVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_pub_bias_var, # Shaded area for credible intervals
                 aes(x = var_lnVR,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_pub_bias_var, # Predicted regression line
               aes(y = emmean,
                   x = var_lnVR,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2.3, -3.25),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Sampling variance of lnVR", y = "lnVR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3.5, 3.5), xlim = c(0, 6))

ggsave(file = "fig/lnVR_pub_bias_var.png", width = 12, height = 7, dpi = 500)

Publication year

Model specification

# Model specification
formula <- bf(lnVR ~ 0 + trait_type:warm_cold + 
                         trait_type:warm_cold:assay_temp_diff + 
                         trait_type:warm_cold:scale(pub_year) + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnVR_model_pub_bias_year <- brm(formula, 
                                            family = gaussian(),
                                            data = data, 
                                            data2 = list(phylo_matrix = phylo_matrix,
                                                         VCV_lnVR = VCV_lnVR),
                                            prior = prior,
                                            control = list(adapt_delta = 0.99, max_treedepth = 15),
                                            iter = 4000, 
                                            warmup = 2000,
                                            chains = 4, 
                                            cores = 4, 
                                            seed = 123) 
# Save model
saveRDS(lnVR_model_pub_bias_year, file = "RData/lnVR_model_pub_bias_year.rds")

Model output

# Load model
lnVR_model_pub_bias_year <- readRDS("RData/lnVR_model_pub_bias_year.rds")

# Display model output 
summary(lnVR_model_pub_bias_year)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + trait_type:warm_cold:scale(pub_year) + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnVR) 
##    Data: data (Number of observations: 476) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 88) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.06     0.00     0.22 1.01      864     2034
## 
## ~obs (Number of levels: 476) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.68      0.03     0.62     0.75 1.00     3134     5430
## 
## ~phylogeny (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.11      0.08     0.00     0.30 1.00     2255     3663
## 
## ~ref (Number of levels: 44) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.08      0.06     0.00
## sd(trait_typefecundity)                          0.09      0.07     0.00
## sd(trait_typesurvival)                           0.20      0.13     0.01
## cor(trait_typebody_size,trait_typefecundity)     0.02      0.50    -0.87
## cor(trait_typebody_size,trait_typesurvival)     -0.02      0.51    -0.88
## cor(trait_typefecundity,trait_typesurvival)     -0.00      0.49    -0.88
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.23 1.00     2885     4406
## sd(trait_typefecundity)                          0.24 1.00     2260     3630
## sd(trait_typesurvival)                           0.50 1.00     1241     3747
## cor(trait_typebody_size,trait_typefecundity)     0.88 1.00     4014     4855
## cor(trait_typebody_size,trait_typesurvival)      0.87 1.00     2156     4340
## cor(trait_typefecundity,trait_typesurvival)      0.87 1.00     3278     4983
## 
## ~species (Number of levels: 25) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.06      0.05     0.00     0.19 1.00     2864     4175
## 
## Regression Coefficients:
##                                                   Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                    -0.04      0.16    -0.35
## trait_typefecundity:warm_coldcold                    -0.26      0.25    -0.76
## trait_typesurvival:warm_coldcold                      0.05      0.41    -0.77
## trait_typebody_size:warm_coldwarm                     0.05      0.13    -0.19
## trait_typefecundity:warm_coldwarm                    -0.12      0.12    -0.37
## trait_typesurvival:warm_coldwarm                      0.27      0.16    -0.04
## trait_typebody_size:warm_coldcold:assay_temp_diff    -0.01      0.03    -0.07
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.20      0.05    -0.31
## trait_typesurvival:warm_coldcold:assay_temp_diff     -0.01      0.05    -0.11
## trait_typebody_size:warm_coldwarm:assay_temp_diff    -0.00      0.02    -0.04
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.02      0.02    -0.01
## trait_typesurvival:warm_coldwarm:assay_temp_diff     -0.02      0.02    -0.07
## trait_typebody_size:warm_coldcold:scalepub_year      -0.09      0.11    -0.30
## trait_typefecundity:warm_coldcold:scalepub_year       0.21      0.19    -0.17
## trait_typesurvival:warm_coldcold:scalepub_year        0.03      0.26    -0.47
## trait_typebody_size:warm_coldwarm:scalepub_year       0.04      0.11    -0.17
## trait_typefecundity:warm_coldwarm:scalepub_year       0.05      0.11    -0.17
## trait_typesurvival:warm_coldwarm:scalepub_year       -0.26      0.12    -0.50
##                                                   u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                     0.28 1.00     2854
## trait_typefecundity:warm_coldcold                     0.24 1.00     3882
## trait_typesurvival:warm_coldcold                      0.86 1.00     4101
## trait_typebody_size:warm_coldwarm                     0.30 1.00     2516
## trait_typefecundity:warm_coldwarm                     0.12 1.00     2638
## trait_typesurvival:warm_coldwarm                      0.59 1.00     2735
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.05 1.00     2677
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.10 1.00     4454
## trait_typesurvival:warm_coldcold:assay_temp_diff      0.08 1.00     3886
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.04 1.00     3382
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.05 1.00     3182
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.02 1.00     3830
## trait_typebody_size:warm_coldcold:scalepub_year       0.13 1.00     2210
## trait_typefecundity:warm_coldcold:scalepub_year       0.58 1.00     4224
## trait_typesurvival:warm_coldcold:scalepub_year        0.54 1.00     3901
## trait_typebody_size:warm_coldwarm:scalepub_year       0.26 1.00     2626
## trait_typefecundity:warm_coldwarm:scalepub_year       0.27 1.00     3255
## trait_typesurvival:warm_coldwarm:scalepub_year       -0.01 1.00     5250
##                                                   Tail_ESS
## trait_typebody_size:warm_coldcold                     3688
## trait_typefecundity:warm_coldcold                     4512
## trait_typesurvival:warm_coldcold                      5122
## trait_typebody_size:warm_coldwarm                     3116
## trait_typefecundity:warm_coldwarm                     3368
## trait_typesurvival:warm_coldwarm                      2998
## trait_typebody_size:warm_coldcold:assay_temp_diff     3881
## trait_typefecundity:warm_coldcold:assay_temp_diff     5516
## trait_typesurvival:warm_coldcold:assay_temp_diff      5024
## trait_typebody_size:warm_coldwarm:assay_temp_diff     4843
## trait_typefecundity:warm_coldwarm:assay_temp_diff     4842
## trait_typesurvival:warm_coldwarm:assay_temp_diff      4994
## trait_typebody_size:warm_coldcold:scalepub_year       3645
## trait_typefecundity:warm_coldcold:scalepub_year       5647
## trait_typesurvival:warm_coldcold:scalepub_year        5028
## trait_typebody_size:warm_coldwarm:scalepub_year       3903
## trait_typefecundity:warm_coldwarm:scalepub_year       4683
## trait_typesurvival:warm_coldwarm:scalepub_year        5690
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnVR_model_pub_bias_year, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `warm_cold` interactions
    Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((cold|warm)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter),
    # Remove "scale" from pub_year
    Parameter = gsub("scalepub_year", "pub_year", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) -0.044 -0.349 0.276
fecundity(cold) -0.259 -0.755 0.241
survival(cold) 0.049 -0.766 0.858
body_size(warm) 0.045 -0.190 0.302
fecundity(warm) -0.123 -0.365 0.119
survival(warm) 0.266 -0.037 0.594
body_size(cold):assay_temp_diff -0.007 -0.066 0.053
fecundity(cold):assay_temp_diff -0.203 -0.309 -0.101
survival(cold):assay_temp_diff -0.015 -0.107 0.079
body_size(warm):assay_temp_diff -0.002 -0.041 0.039
fecundity(warm):assay_temp_diff 0.020 -0.010 0.050
survival(warm):assay_temp_diff -0.024 -0.071 0.022
body_size(cold):pub_year -0.089 -0.303 0.131
fecundity(cold):pub_year 0.207 -0.169 0.583
survival(cold):pub_year 0.035 -0.468 0.539
body_size(warm):pub_year 0.042 -0.172 0.256
fecundity(warm):pub_year 0.050 -0.165 0.266
survival(warm):pub_year -0.258 -0.496 -0.012

Data visualisation

# Generate predictions
emmeans_pub_bias_year <- as.data.frame(emmeans(
  lnVR_model_pub_bias_year,
  specs = ~ pub_year | trait_type * warm_cold,
  at = list(pub_year = seq(min(data$pub_year), max(data$pub_year), by = 1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0


# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_pub_year = min(pub_year),
    max_pub_year = max(pub_year)
  )

emmeans_pub_bias_year$trait_type <- factor(emmeans_pub_bias_year$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_pub_bias_year$warm_cold <- factor(emmeans_pub_bias_year$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_pub_bias_year <- emmeans_pub_bias_year %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    pub_year >= min_pub_year,
    pub_year <= max_pub_year
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = pub_year, 
                      y = lnVR, 
                      size = 1/sqrt(pub_year), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_pub_bias_year, # Shaded area for credible intervals
                 aes(x = pub_year,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_pub_bias_year, # Predicted regression line
               aes(y = emmean,
                   x = pub_year,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2.3, -3.25),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Sampling variance of lnVR", y = "lnVR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none") + 
    coord_cartesian(ylim = c(-3.5, 3.5))

ggsave(file = "fig/lnVR_pub_bias_year.png", width = 12, height = 7, dpi = 500)

Sensitivity analyses

Note that, although mentioned in our pre-registration, we did not compare estimates from peer-reviewed publications and academic theses. This is because only a single included study was a thesis.

Prepare dataset for subset analyses

# Filter to only warm temperatures
data_warm <- filter(data, warm_cold == "Warm")

# Drop tips that are not in the warm dataset
tips_to_drop <- setdiff(phylo_tree$tip.label, data_warm$phylogeny)
phylo_tree_warm <- drop.tip(phylo_tree, tips_to_drop)

# Compute phylogenetic correlation matrix
phylo_matrix_warm <- vcv(phylo_tree_warm, cor = T)  # The vcv function returns a variance-covariance matrix

# Convert tibble to data frame
data_warm <- as.data.frame(data_warm)

# Calculate VCV matrix for all three responses
VCV_lnRR_warm <- vcalc(vi = var_lnRR, cluster = shared_control_ID, rho = 0.5, obs = obs,
    data = data_warm)

VCV_lnCVR_warm <- vcalc(vi = var_lnCVR, cluster = shared_control_ID, rho = 0.5, obs = obs,
    data = data_warm)

VCV_lnVR_warm <- vcalc(vi = var_lnVR, cluster = shared_control_ID, rho = 0.5, obs = obs,
    data = data_warm)

Changes in mean responses (lnRR)

Constant vs. increasing temperatures

Model specification

# Model specification
formula <- bf(lnRR ~ 0 + trait_type:constant_increasing + trait_type:constant_increasing:assay_temp_diff + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix_warm)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnRR_warm)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnRR_model_constant_increasing <- brm(formula, 
                                       family = gaussian(),
                                       data = data_warm, 
                                       data2 = list(phylo_matrix_warm = phylo_matrix_warm,
                                                    VCV_lnRR_warm = VCV_lnRR_warm),
                                       prior = prior,
                                       control = list(adapt_delta = 0.99, max_treedepth = 15),
                                       iter = 4000, 
                                       warmup = 2000,
                                       chains = 4, 
                                       cores = 4, 
                                       seed = 123) 

# Save model
saveRDS(lnRR_model_constant_increasing, file = "RData/lnRR_model_constant_increasing.rds")

Model output

# Load model
lnRR_model_constant_increasing <- readRDS("RData/lnRR_model_constant_increasing.rds")

# Display model output 
summary(lnRR_model_constant_increasing)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnRR ~ 0 + trait_type:constant_increasing + trait_type:constant_increasing:assay_temp_diff + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix_warm)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnRR_warm) 
##    Data: data_warm (Number of observations: 381) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 81) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.00     1181     1279
## 
## ~obs (Number of levels: 381) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.05      0.01     0.04     0.06 1.01     1304     2710
## 
## ~phylogeny (Number of levels: 23) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.02     0.00     0.06 1.00     2344     3808
## 
## ~ref (Number of levels: 38) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.02      0.01     0.00
## sd(trait_typefecundity)                          0.22      0.04     0.15
## sd(trait_typesurvival)                           0.14      0.03     0.09
## cor(trait_typebody_size,trait_typefecundity)    -0.19      0.41    -0.88
## cor(trait_typebody_size,trait_typesurvival)      0.31      0.42    -0.66
## cor(trait_typefecundity,trait_typesurvival)     -0.34      0.47    -0.95
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.04 1.00     1417     2639
## sd(trait_typefecundity)                          0.31 1.00     3306     4983
## sd(trait_typesurvival)                           0.22 1.00     4833     5595
## cor(trait_typebody_size,trait_typefecundity)     0.68 1.01      488      886
## cor(trait_typebody_size,trait_typesurvival)      0.93 1.00     1073     1756
## cor(trait_typefecundity,trait_typesurvival)      0.70 1.01     1070     2328
## 
## ~species (Number of levels: 23) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.00     2742     4545
## 
## Regression Coefficients:
##                                                                   Estimate
## trait_typebody_size:constant_increasingconstant                      -0.01
## trait_typefecundity:constant_increasingconstant                      -0.05
## trait_typesurvival:constant_increasingconstant                        0.02
## trait_typebody_size:constant_increasingincreasing                     0.03
## trait_typefecundity:constant_increasingincreasing                    -0.04
## trait_typesurvival:constant_increasingincreasing                      0.00
## trait_typebody_size:constant_increasingconstant:assay_temp_diff      -0.00
## trait_typefecundity:constant_increasingconstant:assay_temp_diff       0.01
## trait_typesurvival:constant_increasingconstant:assay_temp_diff        0.01
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff     0.00
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff    -0.00
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff     -0.01
##                                                                   Est.Error
## trait_typebody_size:constant_increasingconstant                        0.02
## trait_typefecundity:constant_increasingconstant                        0.06
## trait_typesurvival:constant_increasingconstant                         0.05
## trait_typebody_size:constant_increasingincreasing                      0.04
## trait_typefecundity:constant_increasingincreasing                      0.11
## trait_typesurvival:constant_increasingincreasing                       0.08
## trait_typebody_size:constant_increasingconstant:assay_temp_diff        0.00
## trait_typefecundity:constant_increasingconstant:assay_temp_diff        0.00
## trait_typesurvival:constant_increasingconstant:assay_temp_diff         0.00
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff      0.01
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff      0.01
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff       0.01
##                                                                   l-95% CI
## trait_typebody_size:constant_increasingconstant                      -0.05
## trait_typefecundity:constant_increasingconstant                      -0.16
## trait_typesurvival:constant_increasingconstant                       -0.07
## trait_typebody_size:constant_increasingincreasing                    -0.06
## trait_typefecundity:constant_increasingincreasing                    -0.25
## trait_typesurvival:constant_increasingincreasing                     -0.16
## trait_typebody_size:constant_increasingconstant:assay_temp_diff      -0.00
## trait_typefecundity:constant_increasingconstant:assay_temp_diff      -0.00
## trait_typesurvival:constant_increasingconstant:assay_temp_diff       -0.00
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff    -0.01
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff    -0.02
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff     -0.03
##                                                                   u-95% CI Rhat
## trait_typebody_size:constant_increasingconstant                       0.04 1.00
## trait_typefecundity:constant_increasingconstant                       0.06 1.00
## trait_typesurvival:constant_increasingconstant                        0.11 1.00
## trait_typebody_size:constant_increasingincreasing                     0.10 1.00
## trait_typefecundity:constant_increasingincreasing                     0.17 1.00
## trait_typesurvival:constant_increasingincreasing                      0.17 1.00
## trait_typebody_size:constant_increasingconstant:assay_temp_diff       0.00 1.00
## trait_typefecundity:constant_increasingconstant:assay_temp_diff       0.01 1.00
## trait_typesurvival:constant_increasingconstant:assay_temp_diff        0.01 1.00
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff     0.02 1.00
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff     0.01 1.00
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff      0.01 1.00
##                                                                   Bulk_ESS
## trait_typebody_size:constant_increasingconstant                       3596
## trait_typefecundity:constant_increasingconstant                       3418
## trait_typesurvival:constant_increasingconstant                        4395
## trait_typebody_size:constant_increasingincreasing                     3532
## trait_typefecundity:constant_increasingincreasing                     4370
## trait_typesurvival:constant_increasingincreasing                      4673
## trait_typebody_size:constant_increasingconstant:assay_temp_diff       4760
## trait_typefecundity:constant_increasingconstant:assay_temp_diff       3980
## trait_typesurvival:constant_increasingconstant:assay_temp_diff        5244
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff     5161
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff     8804
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff      6732
##                                                                   Tail_ESS
## trait_typebody_size:constant_increasingconstant                       3668
## trait_typefecundity:constant_increasingconstant                       4083
## trait_typesurvival:constant_increasingconstant                        5340
## trait_typebody_size:constant_increasingincreasing                     3649
## trait_typefecundity:constant_increasingincreasing                     5079
## trait_typesurvival:constant_increasingincreasing                      5498
## trait_typebody_size:constant_increasingconstant:assay_temp_diff       5581
## trait_typefecundity:constant_increasingconstant:assay_temp_diff       6030
## trait_typesurvival:constant_increasingconstant:assay_temp_diff        5166
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff     5335
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff     6882
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff      5784
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnRR_model_constant_increasing, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `constant_increasing` interactions
    Parameter = gsub("trait_type([a-z_]+):constant_increasing(constant|increasing)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((constant|increasing)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(constant) -0.005 -0.047 0.037
fecundity(constant) -0.050 -0.160 0.059
survival(constant) 0.015 -0.074 0.106
body_size(increasing) 0.026 -0.057 0.102
fecundity(increasing) -0.042 -0.251 0.170
survival(increasing) 0.003 -0.162 0.168
body_size(constant):assay_temp_diff -0.001 -0.005 0.002
fecundity(constant):assay_temp_diff 0.006 -0.002 0.015
survival(constant):assay_temp_diff 0.005 -0.001 0.012
body_size(increasing):assay_temp_diff 0.003 -0.011 0.016
fecundity(increasing):assay_temp_diff -0.003 -0.019 0.013
survival(increasing):assay_temp_diff -0.007 -0.026 0.012

Contrasts

# Generate predictions
emms <- emmeans(lnRR_model_constant_increasing, specs = ~constant_increasing | trait_type,
    at = list(assay_temp_diff = 0))

# Generate contrasts
contrast(emms, method = "pairwise")
## trait_type = body_size:
##  contrast              estimate lower.HPD upper.HPD
##  constant - increasing -0.03191    -0.106    0.0427
## 
## trait_type = fecundity:
##  contrast              estimate lower.HPD upper.HPD
##  constant - increasing -0.00587    -0.236    0.2302
## 
## trait_type = survival:
##  contrast              estimate lower.HPD upper.HPD
##  constant - increasing  0.01147    -0.160    0.2028
## 
## Point estimate displayed: median 
## HPD interval probability: 0.95

Data visualisation

# Generate predictions
emmeans_constant_increasing <- as.data.frame(emmeans(lnRR_model_constant_increasing, 
                                                     specs = ~ constant_increasing | trait_type,
                                                     at = list(assay_temp_diff = 0)))

emmeans_constant_increasing$trait_type <- factor(emmeans_constant_increasing$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_constant_increasing$constant_increasing <- factor(emmeans_constant_increasing$constant_increasing, 
                          levels = c("constant", "increasing"), 
                          labels = c("Constant", "Increasing"))

data_warm$constant_increasing <- factor(data_warm$constant_increasing, 
                          levels = c("constant", "increasing"), 
                          labels = c("Constant", "Increasing"))


# Calculate sample sizes and study counts
sample_sizes_warm <- data_warm %>%
  group_by(trait_type, constant_increasing) %>%
  summarise(
    estimates = n(),
    studies = n_distinct(ref)
  )

# Plot
ggplot() +
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75, 
               lwd=1) +
    geom_quasirandom(data = data_warm,     # Plot effect sizes, scaled by precision
                     aes(x = trait_type:constant_increasing, 
                         y = lnRR, 
                         fill = trait_type:constant_increasing, 
                         size = 1/sqrt(var_lnRR)), 
                     color = "black",
                     shape = 21,
                     width = 0.25, 
                     alpha = 0.45) +
    geom_errorbar(data = emmeans_constant_increasing,  # Plot the point estimates in white for background
                  aes(x = trait_type:constant_increasing, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="white",
                  size = 2.5,
                  width = 0.17) +
    geom_point(data = emmeans_constant_increasing,  # Plot the credible intervals in white for background
               aes(x = trait_type:constant_increasing, 
                   y = emmean),
               shape = 21,
               size = 4, 
               stroke = 2,
               color="white",
               fill = "white") +
    geom_errorbar(data = emmeans_constant_increasing, # Plot the point estimates 
                  aes(x = trait_type:constant_increasing, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="black",
                  size = 2,
                  width = 0.15) +
    geom_point(data = emmeans_constant_increasing, # Plot the credible intervals
               aes(x = trait_type:constant_increasing, 
                   y = emmean),
               shape = 21,
               size = 3.5, 
               stroke = 2,
               color="black",
               fill = "white") +
    geom_text(data = sample_sizes_warm,  # Sample size annotations 
              aes(x = trait_type:constant_increasing, 
                  y = 1.5,
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = constant_increasing), 
              hjust = 1, size = 5, show.legend = FALSE) +
    theme_bw() +     # Customize the plot
    labs(y = "lnRR", x = "") +
    scale_size_continuous(range = c(2, 8))+ 
    scale_fill_manual(values = c("#8E77FF", "#FF6040", "#8E77FF", "#FF6040", "#8E77FF", "#FF6040"))+
    scale_color_manual(values = c("Constant" = "#8E77FF", "Increasing" = "#FF6040")) +  # Text colour
    theme(text = element_text(size = 20, color = "black"),
          legend.title = ggplot2::element_text(size = 16),
          legend.text = ggplot2::element_text(size = 14),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
          panel.border = element_rect(color = "black", size = 1.5)) +
    guides(fill = "none", size = "none")+
    coord_flip() + 
    ylim(-1.5, 1.5)

ggsave(file = "fig/lnRR_constant_increasing.png", width = 12, height = 7, dpi = 500)

Leave-one-out analysis

Model specification

# Get a list of study IDs for the LOO
study_ids <- unique(data$ref)
num_studies <- length(study_ids)

# Initialize a list to store the results
loo_results <- vector("list", num_studies)
names(loo_results) <- study_ids

# Set up parallel processing (16 models at a time)
plan(multisession, workers = 16)  

# Model specification
formula <- bf(lnRR ~ trait_type -1 + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnRR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant


# Function to fit the model after iteratively removing one study
leave_one_out <- function(study_id) {
  # Subset the data
  data_subset <- subset(data, ref != study_id)
  
  # Recalculate VCV matrix
  VCV_lnRR_subset <- vcalc(
    vi = var_lnRR,
    cluster = shared_control_ID, 
    rho = 0.5,
    obs = obs,
    data = data_subset
  )
  
  # Fit the model
  model_subset <- brm(
    formula, 
    family = gaussian(),
    data = data_subset, 
    data2 = list(
      phylo_matrix = phylo_matrix,
      VCV_lnRR = VCV_lnRR_subset
    ),
    prior = prior,
    control = list(adapt_delta = 0.99, max_treedepth = 15),
    iter = 2000, # Reduce to 2000 iterations to reduce computational demands
    warmup = 1000, 
    chains = 2, # Only two chains to reduce computational demands
    cores = 1,   # Set cores to 1 inside the function
    seed = 123
  )

  # Extract the fixed effects
  fixed_effects <- fixef(model_subset)
  
  # Return the fixed effects
  return(list(study_id = study_id, fixed_effects = fixed_effects))
}

# Run the function in parallel over the studies
loo_results <- future_lapply(study_ids, leave_one_out)

# Save results
saveRDS(loo_results, file = "RData/lnRR_LOO_results.rds")

Model summary

# Load the list of all model outputs
loo_lnRR <- readRDS(file = "RData/lnRR_LOO_results.rds")

# Extract data on fixed effects from each model

loo_results_lnRR <- do.call(rbind, lapply(loo_lnRR, function(x) {
    # Extract study_id and fixed_effects data
    study_id <- x$study_id
    fixed_effects <- x$fixed_effects

    # Convert row names (trait_type) to a column, remove prefix, and add
    # study_id
    fixed_effects <- data.frame(trait_type = sub("trait_type", "", rownames(fixed_effects)),
        fixed_effects)
    fixed_effects$study_id <- study_id

    # Remove row names
    rownames(fixed_effects) <- NULL

    return(fixed_effects)
}))

loo_results_lnRR$trait_type <- factor(loo_results_lnRR$trait_type, levels = c("body_size",
    "fecundity", "survival"), labels = c("Body size", "Fecundity", "Survival"))

# Summarise the data
loo_results_lnRR %>%
    group_by(trait_type) %>%
    summarise(Estimate = mean(Estimate), SE = mean(Est.Error), lower_CI = mean(Q2.5),
        upper_CI = mean(Q97.5))  # Mean across all models
## # A tibble: 3 × 5
##   trait_type Estimate     SE lower_CI upper_CI
##   <fct>         <dbl>  <dbl>    <dbl>    <dbl>
## 1 Body size  -0.00139 0.0206  -0.0436   0.0396
## 2 Fecundity  -0.0220  0.0438  -0.109    0.0635
## 3 Survival    0.0220  0.0337  -0.0435   0.0906

Data visualisation

# Plot
ggplot() +
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75, 
               lwd=1) +
    geom_errorbar(data = loo_results_lnRR,  # Plot the credible intervals in white for background
               aes(x = study_id, 
                   y = Estimate,
                   ymin = Q2.5, 
                   ymax = Q97.5,
                   color = trait_type),
               shape = 21,
               size = 1,
               width = 0.3) +
    geom_point(data = loo_results_lnRR,
               aes(x = study_id, 
                   y = Estimate,
                   fill = trait_type),
               shape = 21,
               size = 4, 
               stroke = 1,
               color="black") +
    theme_bw() +     # Customize the plot
    labs(y = "lnRR", x = "") +
    scale_fill_manual(values = c("#73B706", "#06A2BA", "#B90674"))+
    scale_color_manual(values = c("#73B706", "#06A2BA", "#B90674")) +  
    theme(text = element_text(size = 20, color = "black"),
          legend.title = ggplot2::element_text(size = 16),
          legend.text = ggplot2::element_text(size = 14),
          axis.text.y = ggplot2::element_text(size = 10, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
          panel.border = element_rect(color = "black", size = 1.5),
          strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 20)) +
    guides(fill = "none", color = "none")+
    coord_flip()+
    xlim(-0.15, 0.15) +
    facet_wrap(~trait_type, ncol = 3)+
    scale_x_discrete(limits = rev(levels(as.factor(loo_results_lnRR$study_id)))) # Alphabetical order

ggsave(file = "fig/lnRR_LOO.png", width = 12, height = 12, dpi = 500)

Unusual study designs

Model specification

# Discard observations flagged because the number of generations of selection was unclear, as this would only affect the results of meta-regressions
data <- mutate(data, minor_concerns2 = ifelse(minor_concerns == "gen_selection approximate" | 
                                               minor_concerns == "gen_selection underestimated",
                     NA, minor_concerns)) 

# Filter to data without sources of procedural  concerns.
data_concerns <- filter(data, is.na(major_concerns)==T & is.na(minor_concerns2)==T)

# Drop tips that are not in the warm dataset
tips_to_drop <- setdiff(phylo_tree$tip.label, data_concerns$phylogeny)
phylo_tree_concerns <- drop.tip(phylo_tree, tips_to_drop)

# Compute phylogenetic correlation matrix
phylo_matrix_concerns <- vcv(phylo_tree_concerns, cor = T)  # The vcv function returns a variance-covariance matrix

# Convert tibble to data frame
data_concerns <- as.data.frame(data_concerns)

# Calculate VCV matrix
VCV_lnRR_concerns <- vcalc(vi = var_lnRR,
                       cluster = shared_control_ID, 
                       rho = 0.5,
                       obs = obs,
                       data = data_concerns) 

# Model specification
formula <- bf(lnRR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix_concerns)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnRR_concerns)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnRR_model_concerns <- brm(formula, 
                                      family = gaussian(),
                                      data = data_concerns, 
                                      data2 = list(phylo_matrix_concerns = phylo_matrix_concerns,
                                                   VCV_lnRR_concerns = VCV_lnRR_concerns),
                                      prior = prior,
                                      control = list(adapt_delta = 0.99, max_treedepth = 15),
                                      iter = 4000, 
                                      warmup = 2000,
                                      chains = 4, 
                                      cores = 4, 
                                      seed = 123) 
# Save model
saveRDS(lnRR_model_concerns, file = "RData/lnRR_model_concerns.rds")

Model summary

# Load model
lnRR_model_concerns <- readRDS("RData/lnRR_model_concerns.rds")

# Display model output
summary(lnRR_model_concerns)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnRR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix_concerns)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnRR_concerns) 
##    Data: data_concerns (Number of observations: 321) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 72) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.04 1.00     1174     1392
## 
## ~obs (Number of levels: 321) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.04      0.00     0.03     0.04 1.00     2135     3894
## 
## ~phylogeny (Number of levels: 22) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.03      0.02     0.00     0.07 1.00     2060     2542
## 
## ~ref (Number of levels: 33) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.02      0.01     0.00
## sd(trait_typefecundity)                          0.25      0.06     0.16
## sd(trait_typesurvival)                           0.12      0.03     0.07
## cor(trait_typebody_size,trait_typefecundity)    -0.05      0.45    -0.88
## cor(trait_typebody_size,trait_typesurvival)      0.16      0.44    -0.77
## cor(trait_typefecundity,trait_typesurvival)     -0.10      0.59    -0.94
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.04 1.00     1269     2073
## sd(trait_typefecundity)                          0.38 1.00     2829     4738
## sd(trait_typesurvival)                           0.20 1.00     4415     5524
## cor(trait_typebody_size,trait_typefecundity)     0.81 1.01      494      944
## cor(trait_typebody_size,trait_typesurvival)      0.90 1.00     1371     2002
## cor(trait_typefecundity,trait_typesurvival)      0.89 1.00      984     3114
## 
## ~species (Number of levels: 22) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.02      0.01     0.00     0.05 1.00     2688     3110
## 
## Regression Coefficients:
##                                                   Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                     0.04      0.02    -0.01
## trait_typefecundity:warm_coldcold                    -0.41      0.11    -0.62
## trait_typesurvival:warm_coldcold                      0.06      0.07    -0.08
## trait_typebody_size:warm_coldwarm                    -0.01      0.02    -0.05
## trait_typefecundity:warm_coldwarm                    -0.06      0.06    -0.19
## trait_typesurvival:warm_coldwarm                     -0.01      0.04    -0.09
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.00      0.00    -0.01
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.08      0.01    -0.09
## trait_typesurvival:warm_coldcold:assay_temp_diff     -0.01      0.01    -0.04
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.00      0.00    -0.00
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.00      0.00    -0.01
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.00      0.00    -0.00
##                                                   u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                     0.09 1.00     2426
## trait_typefecundity:warm_coldcold                    -0.21 1.00     3277
## trait_typesurvival:warm_coldcold                      0.20 1.00     4888
## trait_typebody_size:warm_coldwarm                     0.04 1.00     2763
## trait_typefecundity:warm_coldwarm                     0.07 1.00     2401
## trait_typesurvival:warm_coldwarm                      0.07 1.00     3135
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.01 1.00     3391
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.07 1.00     6613
## trait_typesurvival:warm_coldcold:assay_temp_diff      0.02 1.00     9558
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.00 1.00     4399
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.01 1.00     4738
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.01 1.00     4975
##                                                   Tail_ESS
## trait_typebody_size:warm_coldcold                     3022
## trait_typefecundity:warm_coldcold                     4975
## trait_typesurvival:warm_coldcold                      5736
## trait_typebody_size:warm_coldwarm                     3218
## trait_typefecundity:warm_coldwarm                     3745
## trait_typesurvival:warm_coldwarm                      3671
## trait_typebody_size:warm_coldcold:assay_temp_diff     4414
## trait_typefecundity:warm_coldcold:assay_temp_diff     6434
## trait_typesurvival:warm_coldcold:assay_temp_diff      6100
## trait_typebody_size:warm_coldwarm:assay_temp_diff     5621
## trait_typefecundity:warm_coldwarm:assay_temp_diff     5238
## trait_typesurvival:warm_coldwarm:assay_temp_diff      5722
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnRR_model_concerns, summary = TRUE)) %>%
    # Rename categorical variables for cleaner display
rownames_to_column(var = "Parameter") %>%
    mutate(Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)",
        Parameter), Parameter = gsub("trait_type([a-z_]+)\\(warm\\):assay_temp_diff",
        "\\1(warm): assay_temp_diff", Parameter)) %>%
    # Round numbers to 3 decimal points
mutate(across(c(Estimate, Q2.5, Q97.5), ~round(., 3))) %>%
    select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
    kable() %>%
    kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE) %>%
    row_spec(0, background = "white", color = "black", bold = TRUE) %>%
    kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) 0.038 -0.012 0.086
fecundity(cold) -0.406 -0.619 -0.206
survival(cold) 0.063 -0.076 0.203
body_size(warm) -0.008 -0.055 0.038
fecundity(warm) -0.062 -0.188 0.066
survival(warm) -0.009 -0.089 0.074
body_size(cold):assay_temp_diff 0.000 -0.006 0.007
fecundity(cold):assay_temp_diff -0.077 -0.087 -0.067
survival(cold):assay_temp_diff -0.010 -0.038 0.018
body_size(warm):assay_temp_diff 0.000 -0.004 0.004
fecundity(warm):assay_temp_diff 0.001 -0.007 0.010
survival(warm):assay_temp_diff 0.002 -0.004 0.007

Data visualisation

# Discard observations flagged because the number of generations of selection was unclear, as this would only affect the results of meta-regressions
data <- mutate(data, minor_concerns2 = ifelse(minor_concerns == "gen_selection approximate" | 
                                               minor_concerns == "gen_selection underestimated",
                     NA, minor_concerns)) 

# Filter to data without sources of procedural  concerns.
data_concerns <- filter(data, is.na(major_concerns)==T & is.na(minor_concerns2)==T)

# Calculate sample sizes and study counts
sample_sizes_concerns <- data_concerns %>%
  group_by(trait_type, warm_cold) %>%
  summarise(
    estimates = n(),
    studies = n_distinct(ref)
  )

# Generate predictions
emmeans_concerns <- as.data.frame(emmeans(
  lnRR_model_concerns,
  specs = ~ assay_temp_diff | trait_type * warm_cold,
  at = list(assay_temp_diff = seq(min(data_concerns$assay_temp_diff), max(data_concerns$assay_temp_diff), by = 0.5)))
  )

# Calculate range of values for each category
range_df_concerns <- data_concerns %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_assay_temp_diff = min(assay_temp_diff),
    max_assay_temp_diff = max(assay_temp_diff)
  )

emmeans_concerns$trait_type <- factor(emmeans_concerns$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_concerns$warm_cold <- factor(emmeans_concerns$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_concerns <- emmeans_concerns %>%
  left_join(range_df_concerns, by = c("trait_type", "warm_cold")) %>%
  filter(
    assay_temp_diff >= min_assay_temp_diff,
    assay_temp_diff <= max_assay_temp_diff
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) +  
    geom_vline(xintercept = 0, # Vertical line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data_concerns, # Effect sizes, scaled by precision
                  aes(x = assay_temp_diff, 
                      y = lnRR, 
                      size = 1/sqrt(var_lnRR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_concerns, # Shaded area for credible intervals
                 aes(x = assay_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_concerns,  # Predicted regression line
               aes(y = emmean,
                   x = assay_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) + 
    geom_text(data = sample_sizes_concerns, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -0.9, -1.3),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  
  facet_wrap(~ trait_type, ncol = 1) + # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Assay temperature difference", y = "lnRR",
       col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-1.5, 1.5))

ggsave(file = "fig/lnRR_concerns.png", width = 12, height = 7, dpi = 500)

Changes in relative trait variance (lnCVR)

Constant vs. increasing temperatures

Model specification

# Model specification
formula <- bf(lnCVR ~ 0 + trait_type:constant_increasing + trait_type:constant_increasing:assay_temp_diff + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix_warm)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnCVR_warm)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnCVR_model_constant_increasing <- brm(formula, 
                                       family = gaussian(),
                                       data = data_warm, 
                                       data2 = list(phylo_matrix_warm = phylo_matrix_warm,
                                                    VCV_lnCVR_warm = VCV_lnCVR_warm),
                                       prior = prior,
                                       control = list(adapt_delta = 0.99, max_treedepth = 15),
                                       iter = 4000, 
                                       warmup = 2000,
                                       chains = 4, 
                                       cores = 4, 
                                       seed = 123) 

# Save model
saveRDS(lnCVR_model_constant_increasing, file = "RData/lnCVR_model_constant_increasing.rds")

Model output

# Load model
lnCVR_model_constant_increasing <- readRDS("RData/lnCVR_model_constant_increasing.rds")

# Display model output 
summary(lnCVR_model_constant_increasing)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnCVR ~ 0 + trait_type:constant_increasing + trait_type:constant_increasing:assay_temp_diff + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix_warm)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnCVR_warm) 
##    Data: data_warm (Number of observations: 381) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 81) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.09      0.06     0.00     0.21 1.00     1159     2902
## 
## ~obs (Number of levels: 381) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.44      0.05     0.34     0.54 1.00     2072     3235
## 
## ~phylogeny (Number of levels: 23) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.11      0.09     0.00     0.32 1.00     2872     4272
## 
## ~ref (Number of levels: 38) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.08      0.06     0.00
## sd(trait_typefecundity)                          0.10      0.08     0.00
## sd(trait_typesurvival)                           0.62      0.19     0.31
## cor(trait_typebody_size,trait_typefecundity)     0.00      0.50    -0.87
## cor(trait_typebody_size,trait_typesurvival)     -0.03      0.49    -0.87
## cor(trait_typefecundity,trait_typesurvival)     -0.03      0.47    -0.86
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.23 1.00     3107     3994
## sd(trait_typefecundity)                          0.31 1.00     2207     3874
## sd(trait_typesurvival)                           1.05 1.00     3297     3717
## cor(trait_typebody_size,trait_typefecundity)     0.88 1.00     4662     5294
## cor(trait_typebody_size,trait_typesurvival)      0.87 1.00     1110     2641
## cor(trait_typefecundity,trait_typesurvival)      0.84 1.00     1504     2867
## 
## ~species (Number of levels: 23) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.08      0.06     0.00     0.23 1.00     3018     4221
## 
## Regression Coefficients:
##                                                                   Estimate
## trait_typebody_size:constant_increasingconstant                       0.06
## trait_typefecundity:constant_increasingconstant                      -0.06
## trait_typesurvival:constant_increasingconstant                        0.28
## trait_typebody_size:constant_increasingincreasing                    -0.08
## trait_typefecundity:constant_increasingincreasing                     0.02
## trait_typesurvival:constant_increasingincreasing                      0.18
## trait_typebody_size:constant_increasingconstant:assay_temp_diff      -0.00
## trait_typefecundity:constant_increasingconstant:assay_temp_diff       0.02
## trait_typesurvival:constant_increasingconstant:assay_temp_diff       -0.03
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff     0.07
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff     0.01
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff     -0.03
##                                                                   Est.Error
## trait_typebody_size:constant_increasingconstant                        0.13
## trait_typefecundity:constant_increasingconstant                        0.12
## trait_typesurvival:constant_increasingconstant                         0.24
## trait_typebody_size:constant_increasingincreasing                      0.28
## trait_typefecundity:constant_increasingincreasing                      0.19
## trait_typesurvival:constant_increasingincreasing                       0.46
## trait_typebody_size:constant_increasingconstant:assay_temp_diff        0.02
## trait_typefecundity:constant_increasingconstant:assay_temp_diff        0.02
## trait_typesurvival:constant_increasingconstant:assay_temp_diff         0.03
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff      0.06
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff      0.04
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff       0.06
##                                                                   l-95% CI
## trait_typebody_size:constant_increasingconstant                      -0.18
## trait_typefecundity:constant_increasingconstant                      -0.31
## trait_typesurvival:constant_increasingconstant                       -0.18
## trait_typebody_size:constant_increasingincreasing                    -0.63
## trait_typefecundity:constant_increasingincreasing                    -0.34
## trait_typesurvival:constant_increasingincreasing                     -0.71
## trait_typebody_size:constant_increasingconstant:assay_temp_diff      -0.04
## trait_typefecundity:constant_increasingconstant:assay_temp_diff      -0.02
## trait_typesurvival:constant_increasingconstant:assay_temp_diff       -0.08
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff    -0.05
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff    -0.07
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff     -0.16
##                                                                   u-95% CI Rhat
## trait_typebody_size:constant_increasingconstant                       0.33 1.00
## trait_typefecundity:constant_increasingconstant                       0.18 1.00
## trait_typesurvival:constant_increasingconstant                        0.76 1.00
## trait_typebody_size:constant_increasingincreasing                     0.49 1.00
## trait_typefecundity:constant_increasingincreasing                     0.41 1.00
## trait_typesurvival:constant_increasingincreasing                      1.12 1.00
## trait_typebody_size:constant_increasingconstant:assay_temp_diff       0.03 1.00
## trait_typefecundity:constant_increasingconstant:assay_temp_diff       0.06 1.00
## trait_typesurvival:constant_increasingconstant:assay_temp_diff        0.03 1.00
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff     0.18 1.00
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff     0.08 1.00
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff      0.09 1.00
##                                                                   Bulk_ESS
## trait_typebody_size:constant_increasingconstant                       2678
## trait_typefecundity:constant_increasingconstant                       3157
## trait_typesurvival:constant_increasingconstant                        4163
## trait_typebody_size:constant_increasingincreasing                     4000
## trait_typefecundity:constant_increasingincreasing                     3696
## trait_typesurvival:constant_increasingincreasing                      4982
## trait_typebody_size:constant_increasingconstant:assay_temp_diff       4749
## trait_typefecundity:constant_increasingconstant:assay_temp_diff       4943
## trait_typesurvival:constant_increasingconstant:assay_temp_diff        5797
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff     5135
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff     5524
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff      6663
##                                                                   Tail_ESS
## trait_typebody_size:constant_increasingconstant                       3348
## trait_typefecundity:constant_increasingconstant                       3664
## trait_typesurvival:constant_increasingconstant                        4445
## trait_typebody_size:constant_increasingincreasing                     5079
## trait_typefecundity:constant_increasingincreasing                     4163
## trait_typesurvival:constant_increasingincreasing                      5028
## trait_typebody_size:constant_increasingconstant:assay_temp_diff       5921
## trait_typefecundity:constant_increasingconstant:assay_temp_diff       5730
## trait_typesurvival:constant_increasingconstant:assay_temp_diff        6127
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff     5816
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff     5587
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff      6404
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnCVR_model_constant_increasing, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `constant_increasing` interactions
    Parameter = gsub("trait_type([a-z_]+):constant_increasing(constant|increasing)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((constant|increasing)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(constant) 0.061 -0.175 0.330
fecundity(constant) -0.063 -0.314 0.184
survival(constant) 0.280 -0.178 0.757
body_size(increasing) -0.076 -0.632 0.490
fecundity(increasing) 0.019 -0.342 0.415
survival(increasing) 0.185 -0.712 1.122
body_size(constant):assay_temp_diff -0.004 -0.041 0.033
fecundity(constant):assay_temp_diff 0.020 -0.016 0.056
survival(constant):assay_temp_diff -0.028 -0.082 0.027
body_size(increasing):assay_temp_diff 0.066 -0.052 0.181
fecundity(increasing):assay_temp_diff 0.007 -0.068 0.083
survival(increasing):assay_temp_diff -0.031 -0.157 0.094

Contrasts

# Generate predictions
emms <- emmeans(lnCVR_model_constant_increasing, specs = ~constant_increasing | trait_type,
    at = list(assay_temp_diff = 0))

# Generate contrasts
contrast(emms, method = "pairwise")
## trait_type = body_size:
##  contrast              estimate lower.HPD upper.HPD
##  constant - increasing   0.1337    -0.400     0.717
## 
## trait_type = fecundity:
##  contrast              estimate lower.HPD upper.HPD
##  constant - increasing  -0.0765    -0.483     0.326
## 
## trait_type = survival:
##  contrast              estimate lower.HPD upper.HPD
##  constant - increasing   0.1066    -0.870     1.087
## 
## Point estimate displayed: median 
## HPD interval probability: 0.95

Data visualisation

# Generate predictions
emmeans_constant_increasing <- as.data.frame(emmeans(lnCVR_model_constant_increasing, 
                                                     specs = ~ constant_increasing | trait_type,
                                                     at = list(assay_temp_diff = 0)))

emmeans_constant_increasing$trait_type <- factor(emmeans_constant_increasing$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_constant_increasing$constant_increasing <- factor(emmeans_constant_increasing$constant_increasing, 
                          levels = c("constant", "increasing"), 
                          labels = c("Constant", "Increasing"))

# Plot
ggplot() +
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75, 
               lwd=1) +
    geom_quasirandom(data = data_warm,     # Plot effect sizes, scaled by precision
                     aes(x = trait_type:constant_increasing, 
                         y = lnCVR, 
                         fill = trait_type:constant_increasing, 
                         size = 1/sqrt(var_lnCVR)), 
                     color = "black",
                     shape = 21,
                     width = 0.25, 
                     alpha = 0.45) +
    geom_errorbar(data = emmeans_constant_increasing,  # Plot the point estimates in white for background
                  aes(x = trait_type:constant_increasing, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="white",
                  size = 2.5,
                  width = 0.17) +
    geom_point(data = emmeans_constant_increasing,  # Plot the credible intervals in white for background
               aes(x = trait_type:constant_increasing, 
                   y = emmean),
               shape = 21,
               size = 4, 
               stroke = 2,
               color="white",
               fill = "white") +
    geom_errorbar(data = emmeans_constant_increasing, # Plot the point estimates 
                  aes(x = trait_type:constant_increasing, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="black",
                  size = 2,
                  width = 0.15) +
    geom_point(data = emmeans_constant_increasing, # Plot the credible intervals
               aes(x = trait_type:constant_increasing, 
                   y = emmean),
               shape = 21,
               size = 3.5, 
               stroke = 2,
               color="black",
               fill = "white") +
    geom_text(data = sample_sizes_warm,  # Sample size annotations 
              aes(x = trait_type:constant_increasing, 
                  y = 3,
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = constant_increasing), 
              hjust = 1, size = 5, show.legend = FALSE) +
    theme_bw() +     # Customize the plot
    labs(y = "lnCVR", x = "") +
    scale_size_continuous(range = c(2, 8))+ 
    scale_fill_manual(values = c("#8E77FF", "#FF6040", "#8E77FF", "#FF6040", "#8E77FF", "#FF6040"))+
    scale_color_manual(values = c("Constant" = "#8E77FF", "Increasing" = "#FF6040")) +  # Text colour
    theme(text = element_text(size = 20, color = "black"),
          legend.title = ggplot2::element_text(size = 16),
          legend.text = ggplot2::element_text(size = 14),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
          panel.border = element_rect(color = "black", size = 1.5)) +
    guides(fill = "none", size = "none")+
    coord_flip() + 
    ylim(-3, 3)

ggsave(file = "fig/lnCVR_constant_increasing.png", width = 12, height = 7, dpi = 500)

Leave-one-out analysis

Model specification

# Get a list of study IDs for the LOO
study_ids <- unique(data$ref)
num_studies <- length(study_ids)

# Initialize a list to store the results
loo_results <- vector("list", num_studies)
names(loo_results) <- study_ids

# Set up parallel processing (16 models at a time)
plan(multisession, workers = 16)  

# Model specification
formula <- bf(lnCVR ~ trait_type -1 + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnCVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant


# Function to fit the model after iteratively removing one study
leave_one_out <- function(study_id) {
  # Subset the data
  data_subset <- subset(data, ref != study_id)
  
  # Recalculate VCV matrix
  VCV_lnCVR_subset <- vcalc(
    vi = var_lnCVR,
    cluster = shared_control_ID, 
    rho = 0.5,
    obs = obs,
    data = data_subset
  )
  
  # Fit the model
  model_subset <- brm(
    formula, 
    family = gaussian(),
    data = data_subset, 
    data2 = list(
      phylo_matrix = phylo_matrix,
      VCV_lnCVR = VCV_lnCVR_subset
    ),
    prior = prior,
    control = list(adapt_delta = 0.99, max_treedepth = 15),
    iter = 2000, # Reduce to 2000 iterations to reduce computational demands
    warmup = 1000, 
    chains = 2, # Only two chains to reduce computational demands
    cores = 1,   # Set cores to 1 inside the function
    seed = 123
  )

  # Extract the fixed effects
  fixed_effects <- fixef(model_subset)
  
  # Return the fixed effects
  return(list(study_id = study_id, fixed_effects = fixed_effects))
}

# Run the function in parallel over the studies
loo_results <- future_lapply(study_ids, leave_one_out)

# Save results
saveRDS(loo_results, file = "RData/lnCVR_LOO_results.rds")

Model summary

# Load the list of all model outputs
loo_lnCVR <- readRDS(file = "RData/lnCVR_LOO_results.rds")

# Extract data on fixed effects from each model

loo_results_lnCVR <- do.call(rbind, lapply(loo_lnCVR, function(x) {
    # Extract study_id and fixed_effects data
    study_id <- x$study_id
    fixed_effects <- x$fixed_effects

    # Convert row names (trait_type) to a column, remove prefix, and add
    # study_id
    fixed_effects <- data.frame(trait_type = sub("trait_type", "", rownames(fixed_effects)),
        fixed_effects)
    fixed_effects$study_id <- study_id

    # Remove row names
    rownames(fixed_effects) <- NULL

    return(fixed_effects)
}))

loo_results_lnCVR$trait_type <- factor(loo_results_lnCVR$trait_type, levels = c("body_size",
    "fecundity", "survival"), labels = c("Body size", "Fecundity", "Survival"))

# Summarise the data
loo_results_lnCVR %>%
    group_by(trait_type) %>%
    summarise(Estimate = mean(Estimate), SE = mean(Est.Error), lower_CI = mean(Q2.5),
        upper_CI = mean(Q97.5))  # Mean across all models
## # A tibble: 3 × 5
##   trait_type Estimate     SE lower_CI upper_CI
##   <fct>         <dbl>  <dbl>    <dbl>    <dbl>
## 1 Body size    0.0443 0.0985   -0.139    0.254
## 2 Fecundity   -0.0115 0.101    -0.204    0.197
## 3 Survival     0.129  0.159    -0.181    0.448

Data visualisation

# Plot
ggplot() +
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75, 
               lwd=1) +
    geom_errorbar(data = loo_results_lnCVR,  # Plot the credible intervals in white for background
               aes(x = study_id, 
                   y = Estimate,
                   ymin = Q2.5, 
                   ymax = Q97.5,
                   color = trait_type),
               shape = 21,
               size = 1,
               width = 0.3) +
    geom_point(data = loo_results_lnCVR,
               aes(x = study_id, 
                   y = Estimate,
                   fill = trait_type),
               shape = 21,
               size = 4, 
               stroke = 1,
               color="black") +
    theme_bw() +     # Customize the plot
    labs(y = "lnCVR", x = "") +
    scale_fill_manual(values = c("#73B706", "#06A2BA", "#B90674"))+
    scale_color_manual(values = c("#73B706", "#06A2BA", "#B90674")) +  
    theme(text = element_text(size = 20, color = "black"),
          legend.title = ggplot2::element_text(size = 16),
          legend.text = ggplot2::element_text(size = 14),
          axis.text.y = ggplot2::element_text(size = 10, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
          panel.border = element_rect(color = "black", size = 1.5),
          strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 20)) +
    guides(fill = "none", color = "none")+
    coord_flip()+
    xlim(-0.4, 0.4)+
    facet_wrap(~trait_type, ncol = 3)+
   scale_x_discrete(limits = rev(levels(as.factor(loo_results_lnCVR$study_id)))) # Alphabetical order

ggsave(file = "fig/lnCVR_LOO.png", width = 12, height = 12, dpi = 500)

Unusual study designs

Model specification

# Discard observations flagged because the number of generations of selection was unclear, as this would only affect the results of meta-regressions
data <- mutate(data, minor_concerns2 = ifelse(minor_concerns == "gen_selection approximate" | 
                                               minor_concerns == "gen_selection underestimated",
                     NA, minor_concerns)) 

# Filter to data without sources of procedural  concerns.
data_concerns <- filter(data, is.na(major_concerns)==T & is.na(minor_concerns2)==T)

# Drop tips that are not in the warm dataset
tips_to_drop <- setdiff(phylo_tree$tip.label, data_concerns$phylogeny)
phylo_tree_concerns <- drop.tip(phylo_tree, tips_to_drop)

# Compute phylogenetic correlation matrix
phylo_matrix_concerns <- vcv(phylo_tree_concerns, cor = T)  # The vcv function returns a variance-covariance matrix

# Convert tibble to data frame
data_concerns <- as.data.frame(data_concerns)

# Calculate VCV matrix
VCV_lnCVR_concerns <- vcalc(vi = var_lnCVR,
                       cluster = shared_control_ID, 
                       rho = 0.5,
                       obs = obs,
                       data = data_concerns) 

# Model specification
formula <- bf(lnCVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix_concerns)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnCVR_concerns)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnCVR_model_concerns <- brm(formula, 
                                      family = gaussian(),
                                      data = data_concerns, 
                                      data2 = list(phylo_matrix_concerns = phylo_matrix_concerns,
                                                   VCV_lnCVR_concerns = VCV_lnCVR_concerns),
                                      prior = prior,
                                      control = list(adapt_delta = 0.99, max_treedepth = 15),
                                      iter = 4000, 
                                      warmup = 2000,
                                      chains = 4, 
                                      cores = 4, 
                                      seed = 123) 
# Save model
saveRDS(lnCVR_model_concerns, file = "RData/lnCVR_model_concerns.rds")

Model summary

# Load model
lnCVR_model_concerns <- readRDS("RData/lnCVR_model_concerns.rds")

# Display model output
summary(lnCVR_model_concerns)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnCVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix_concerns)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnCVR_concerns) 
##    Data: data_concerns (Number of observations: 321) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 72) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.13      0.07     0.01     0.26 1.00     1347     2050
## 
## ~obs (Number of levels: 321) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.41      0.06     0.29     0.53 1.00     1660     3010
## 
## ~phylogeny (Number of levels: 22) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.10      0.09     0.00     0.32 1.00     3339     4425
## 
## ~ref (Number of levels: 33) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.08      0.07     0.00
## sd(trait_typefecundity)                          0.11      0.09     0.00
## sd(trait_typesurvival)                           0.68      0.21     0.33
## cor(trait_typebody_size,trait_typefecundity)     0.04      0.49    -0.86
## cor(trait_typebody_size,trait_typesurvival)     -0.06      0.50    -0.90
## cor(trait_typefecundity,trait_typesurvival)     -0.07      0.47    -0.87
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.24 1.00     3827     4841
## sd(trait_typefecundity)                          0.33 1.00     2626     3833
## sd(trait_typesurvival)                           1.17 1.00     3113     4527
## cor(trait_typebody_size,trait_typefecundity)     0.88 1.00     5647     5687
## cor(trait_typebody_size,trait_typesurvival)      0.87 1.00     1193     2127
## cor(trait_typefecundity,trait_typesurvival)      0.83 1.00     1742     3608
## 
## ~species (Number of levels: 22) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.08      0.06     0.00     0.25 1.00     3552     4619
## 
## Regression Coefficients:
##                                                   Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                     0.07      0.17    -0.25
## trait_typefecundity:warm_coldcold                    -0.21      0.31    -0.83
## trait_typesurvival:warm_coldcold                      0.15      0.55    -0.90
## trait_typebody_size:warm_coldwarm                     0.00      0.13    -0.25
## trait_typefecundity:warm_coldwarm                    -0.03      0.12    -0.27
## trait_typesurvival:warm_coldwarm                      0.26      0.24    -0.20
## trait_typebody_size:warm_coldcold:assay_temp_diff    -0.04      0.06    -0.15
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.14      0.06    -0.26
## trait_typesurvival:warm_coldcold:assay_temp_diff     -0.00      0.12    -0.24
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.02      0.02    -0.02
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.02      0.02    -0.02
## trait_typesurvival:warm_coldwarm:assay_temp_diff     -0.03      0.03    -0.08
##                                                   u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                     0.39 1.00     3506
## trait_typefecundity:warm_coldcold                     0.38 1.00     4899
## trait_typesurvival:warm_coldcold                      1.24 1.00     6366
## trait_typebody_size:warm_coldwarm                     0.26 1.00     3482
## trait_typefecundity:warm_coldwarm                     0.22 1.00     3891
## trait_typesurvival:warm_coldwarm                      0.75 1.00     4052
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.07 1.00     7840
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.02 1.00     6417
## trait_typesurvival:warm_coldcold:assay_temp_diff      0.24 1.00     9296
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.07 1.00     4828
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.06 1.00     6885
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.03 1.00     6289
##                                                   Tail_ESS
## trait_typebody_size:warm_coldcold                     4975
## trait_typefecundity:warm_coldcold                     5488
## trait_typesurvival:warm_coldcold                      5853
## trait_typebody_size:warm_coldwarm                     4019
## trait_typefecundity:warm_coldwarm                     3551
## trait_typesurvival:warm_coldwarm                      4079
## trait_typebody_size:warm_coldcold:assay_temp_diff     6553
## trait_typefecundity:warm_coldcold:assay_temp_diff     6530
## trait_typesurvival:warm_coldcold:assay_temp_diff      6783
## trait_typebody_size:warm_coldwarm:assay_temp_diff     6069
## trait_typefecundity:warm_coldwarm:assay_temp_diff     6018
## trait_typesurvival:warm_coldwarm:assay_temp_diff      6417
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnCVR_model_concerns, summary = TRUE)) %>%
    # Rename categorical variables for cleaner display
rownames_to_column(var = "Parameter") %>%
    mutate(Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)",
        Parameter), Parameter = gsub("trait_type([a-z_]+)\\(warm\\):assay_temp_diff",
        "\\1(warm): assay_temp_diff", Parameter)) %>%
    # Round numbers to 3 decimal points
mutate(across(c(Estimate, Q2.5, Q97.5), ~round(., 3))) %>%
    select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
    kable() %>%
    kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE) %>%
    row_spec(0, background = "white", color = "black", bold = TRUE) %>%
    kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) 0.068 -0.251 0.393
fecundity(cold) -0.214 -0.831 0.384
survival(cold) 0.155 -0.897 1.244
body_size(warm) 0.002 -0.250 0.263
fecundity(warm) -0.031 -0.266 0.220
survival(warm) 0.260 -0.198 0.749
body_size(cold):assay_temp_diff -0.042 -0.152 0.071
fecundity(cold):assay_temp_diff -0.135 -0.256 -0.016
survival(cold):assay_temp_diff -0.004 -0.243 0.236
body_size(warm):assay_temp_diff 0.020 -0.024 0.065
fecundity(warm):assay_temp_diff 0.020 -0.015 0.056
survival(warm):assay_temp_diff -0.029 -0.083 0.026

Data visualisation

# Discard observations flagged because the number of generations of selection was unclear, as this would only affect the results of meta-regressions
data <- mutate(data, minor_concerns2 = ifelse(minor_concerns == "gen_selection approximate" | 
                                               minor_concerns == "gen_selection underestimated",
                     NA, minor_concerns)) 

# Filter to data without sources of procedural  concerns.
data_concerns <- filter(data, is.na(major_concerns)==T & is.na(minor_concerns2)==T)

# Calculate sample sizes and study counts
sample_sizes_concerns <- data_concerns %>%
  group_by(trait_type, warm_cold) %>%
  summarise(
    estimates = n(),
    studies = n_distinct(ref)
  )

# Generate predictions
emmeans_concerns <- as.data.frame(emmeans(
  lnCVR_model_concerns,
  specs = ~ assay_temp_diff | trait_type * warm_cold,
  at = list(assay_temp_diff = seq(min(data_concerns$assay_temp_diff), max(data_concerns$assay_temp_diff), by = 0.5))))

# Calculate range of values for each category
range_df_concerns <- data_concerns %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_assay_temp_diff = min(assay_temp_diff),
    max_assay_temp_diff = max(assay_temp_diff)
  )

emmeans_concerns$trait_type <- factor(emmeans_concerns$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_concerns$warm_cold <- factor(emmeans_concerns$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_concerns <- emmeans_concerns %>%
  left_join(range_df_concerns, by = c("trait_type", "warm_cold")) %>%
  filter(
    assay_temp_diff >= min_assay_temp_diff,
    assay_temp_diff <= max_assay_temp_diff
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) +  
    geom_vline(xintercept = 0, # Vertical line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data_concerns, # Effect sizes, scaled by precision
                  aes(x = assay_temp_diff, 
                      y = lnCVR, 
                      size = 1/sqrt(var_lnCVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_concerns, # Shaded area for credible intervals
                 aes(x = assay_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_concerns,  # Predicted regression line
               aes(y = emmean,
                   x = assay_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) + 
    geom_text(data = sample_sizes_concerns, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  
  facet_wrap(~ trait_type, ncol = 1) + # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Assay temperature difference", y = "lnCVR",
       col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3, 3))

ggsave(file = "fig/lnCVR_concerns.png", width = 12, height = 7, dpi = 500)

Changes in trait variance (lnVR)

Constant vs. increasing temperatures

Model specification

# Model specification
formula <- bf(lnVR ~ 0 + trait_type:constant_increasing + trait_type:constant_increasing:assay_temp_diff + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix_warm)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnVR_warm)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnVR_model_constant_increasing <- brm(formula, 
                                       family = gaussian(),
                                       data = data_warm, 
                                       data2 = list(phylo_matrix_warm = phylo_matrix_warm,
                                                    VCV_lnVR_warm = VCV_lnVR_warm),
                                       prior = prior,
                                       control = list(adapt_delta = 0.99, max_treedepth = 15),
                                       iter = 4000, 
                                       warmup = 2000,
                                       chains = 4, 
                                       cores = 4, 
                                       seed = 123) 

# Save model
saveRDS(lnVR_model_constant_increasing, file = "RData/lnVR_model_constant_increasing.rds")

Model output

# Load model
lnVR_model_constant_increasing <- readRDS("RData/lnVR_model_constant_increasing.rds")

# Display model output 
summary(lnVR_model_constant_increasing)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnVR ~ 0 + trait_type:constant_increasing + trait_type:constant_increasing:assay_temp_diff + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix_warm)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnVR_warm) 
##    Data: data_warm (Number of observations: 381) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 81) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.10      0.06     0.00     0.24 1.01      590     1729
## 
## ~obs (Number of levels: 381) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.76      0.04     0.68     0.84 1.00     2368     4730
## 
## ~phylogeny (Number of levels: 23) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.12      0.09     0.01     0.35 1.00     1683     3203
## 
## ~ref (Number of levels: 38) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.09      0.08     0.00
## sd(trait_typefecundity)                          0.10      0.08     0.00
## sd(trait_typesurvival)                           0.31      0.18     0.02
## cor(trait_typebody_size,trait_typefecundity)     0.02      0.50    -0.88
## cor(trait_typebody_size,trait_typesurvival)     -0.02      0.49    -0.89
## cor(trait_typefecundity,trait_typesurvival)     -0.02      0.49    -0.88
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.28 1.00     1982     3248
## sd(trait_typefecundity)                          0.29 1.00     1449     2442
## sd(trait_typesurvival)                           0.68 1.00      994     1772
## cor(trait_typebody_size,trait_typefecundity)     0.89 1.00     3136     4437
## cor(trait_typebody_size,trait_typesurvival)      0.85 1.00     1634     3846
## cor(trait_typefecundity,trait_typesurvival)      0.86 1.00     1835     3569
## 
## ~species (Number of levels: 23) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.08      0.06     0.00     0.23 1.00     1989     3398
## 
## Regression Coefficients:
##                                                                   Estimate
## trait_typebody_size:constant_increasingconstant                       0.05
## trait_typefecundity:constant_increasingconstant                      -0.15
## trait_typesurvival:constant_increasingconstant                        0.25
## trait_typebody_size:constant_increasingincreasing                    -0.11
## trait_typefecundity:constant_increasingincreasing                     0.01
## trait_typesurvival:constant_increasingincreasing                      0.06
## trait_typebody_size:constant_increasingconstant:assay_temp_diff      -0.01
## trait_typefecundity:constant_increasingconstant:assay_temp_diff       0.03
## trait_typesurvival:constant_increasingconstant:assay_temp_diff       -0.02
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff     0.08
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff    -0.01
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff     -0.01
##                                                                   Est.Error
## trait_typebody_size:constant_increasingconstant                        0.15
## trait_typefecundity:constant_increasingconstant                        0.14
## trait_typesurvival:constant_increasingconstant                         0.19
## trait_typebody_size:constant_increasingincreasing                      0.34
## trait_typefecundity:constant_increasingincreasing                      0.21
## trait_typesurvival:constant_increasingincreasing                       0.38
## trait_typebody_size:constant_increasingconstant:assay_temp_diff        0.02
## trait_typefecundity:constant_increasingconstant:assay_temp_diff        0.02
## trait_typesurvival:constant_increasingconstant:assay_temp_diff         0.03
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff      0.07
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff      0.04
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff       0.06
##                                                                   l-95% CI
## trait_typebody_size:constant_increasingconstant                      -0.24
## trait_typefecundity:constant_increasingconstant                      -0.42
## trait_typesurvival:constant_increasingconstant                       -0.12
## trait_typebody_size:constant_increasingincreasing                    -0.78
## trait_typefecundity:constant_increasingincreasing                    -0.39
## trait_typesurvival:constant_increasingincreasing                     -0.65
## trait_typebody_size:constant_increasingconstant:assay_temp_diff      -0.05
## trait_typefecundity:constant_increasingconstant:assay_temp_diff      -0.01
## trait_typesurvival:constant_increasingconstant:assay_temp_diff       -0.08
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff    -0.06
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff    -0.10
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff     -0.13
##                                                                   u-95% CI Rhat
## trait_typebody_size:constant_increasingconstant                       0.34 1.00
## trait_typefecundity:constant_increasingconstant                       0.12 1.00
## trait_typesurvival:constant_increasingconstant                        0.65 1.00
## trait_typebody_size:constant_increasingincreasing                     0.55 1.00
## trait_typefecundity:constant_increasingincreasing                     0.44 1.00
## trait_typesurvival:constant_increasingincreasing                      0.85 1.00
## trait_typebody_size:constant_increasingconstant:assay_temp_diff       0.03 1.00
## trait_typefecundity:constant_increasingconstant:assay_temp_diff       0.06 1.00
## trait_typesurvival:constant_increasingconstant:assay_temp_diff        0.03 1.00
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff     0.21 1.00
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff     0.08 1.00
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff      0.11 1.00
##                                                                   Bulk_ESS
## trait_typebody_size:constant_increasingconstant                       1777
## trait_typefecundity:constant_increasingconstant                       1885
## trait_typesurvival:constant_increasingconstant                        2607
## trait_typebody_size:constant_increasingincreasing                     1761
## trait_typefecundity:constant_increasingincreasing                     2068
## trait_typesurvival:constant_increasingincreasing                      2201
## trait_typebody_size:constant_increasingconstant:assay_temp_diff       2536
## trait_typefecundity:constant_increasingconstant:assay_temp_diff       2178
## trait_typesurvival:constant_increasingconstant:assay_temp_diff        2867
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff     2042
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff     2463
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff      2589
##                                                                   Tail_ESS
## trait_typebody_size:constant_increasingconstant                       2909
## trait_typefecundity:constant_increasingconstant                       3615
## trait_typesurvival:constant_increasingconstant                        3794
## trait_typebody_size:constant_increasingincreasing                     3411
## trait_typefecundity:constant_increasingincreasing                     4043
## trait_typesurvival:constant_increasingincreasing                      3335
## trait_typebody_size:constant_increasingconstant:assay_temp_diff       3923
## trait_typefecundity:constant_increasingconstant:assay_temp_diff       3832
## trait_typesurvival:constant_increasingconstant:assay_temp_diff        4642
## trait_typebody_size:constant_increasingincreasing:assay_temp_diff     3380
## trait_typefecundity:constant_increasingincreasing:assay_temp_diff     3799
## trait_typesurvival:constant_increasingincreasing:assay_temp_diff      4030
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnVR_model_constant_increasing, summary = TRUE)) %>%
  # Rename categorical variables for cleaner display
  rownames_to_column(var = "Parameter") %>%
  mutate(
    # Simplify `trait_type` and `constant_increasing` interactions
    Parameter = gsub("trait_type([a-z_]+):constant_increasing(constant|increasing)", "\\1(\\2)", Parameter),
    # Adjust for assay_temp_diff
    Parameter = gsub("trait_type([a-z_]+)\\((constant|increasing)\\):assay_temp_diff", "\\1(\\2): assay_temp_diff", Parameter)
  ) %>%
  # Round numbers to 3 decimal points
  mutate(across(c(Estimate, Q2.5, Q97.5), ~ round(., 3))) %>%
  select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
  kable() %>%
  kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE) %>%
  row_spec(0, background = "white", color = "black", bold = TRUE) %>%
  kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(constant) 0.045 -0.237 0.343
fecundity(constant) -0.146 -0.418 0.124
survival(constant) 0.253 -0.117 0.646
body_size(increasing) -0.114 -0.777 0.550
fecundity(increasing) 0.014 -0.394 0.445
survival(increasing) 0.065 -0.646 0.855
body_size(constant):assay_temp_diff -0.009 -0.054 0.034
fecundity(constant):assay_temp_diff 0.025 -0.010 0.061
survival(constant):assay_temp_diff -0.024 -0.079 0.031
body_size(increasing):assay_temp_diff 0.076 -0.063 0.213
fecundity(increasing):assay_temp_diff -0.009 -0.096 0.078
survival(increasing):assay_temp_diff -0.009 -0.133 0.109

Contrasts

# Generate predictions
emms <- emmeans(lnVR_model_constant_increasing, specs = ~constant_increasing | trait_type,
    at = list(assay_temp_diff = 0))

# Generate contrasts
contrast(emms, method = "pairwise")
## trait_type = body_size:
##  contrast              estimate lower.HPD upper.HPD
##  constant - increasing    0.156    -0.541     0.824
## 
## trait_type = fecundity:
##  contrast              estimate lower.HPD upper.HPD
##  constant - increasing   -0.157    -0.620     0.277
## 
## trait_type = survival:
##  contrast              estimate lower.HPD upper.HPD
##  constant - increasing    0.205    -0.610     0.969
## 
## Point estimate displayed: median 
## HPD interval probability: 0.95

Data visualisation

# Generate predictions
emmeans_constant_increasing <- as.data.frame(emmeans(lnVR_model_constant_increasing, 
                                                     specs = ~ constant_increasing | trait_type,
                                                     at = list(assay_temp_diff = 0)))

emmeans_constant_increasing$trait_type <- factor(emmeans_constant_increasing$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_constant_increasing$constant_increasing <- factor(emmeans_constant_increasing$constant_increasing, 
                          levels = c("constant", "increasing"), 
                          labels = c("Constant", "Increasing"))

# Plot
ggplot() +
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75, 
               lwd=1) +
    geom_quasirandom(data = data_warm,     # Plot effect sizes, scaled by precision
                     aes(x = trait_type:constant_increasing, 
                         y = lnVR, 
                         fill = trait_type:constant_increasing, 
                         size = 1/sqrt(var_lnVR)), 
                     color = "black",
                     shape = 21,
                     width = 0.25, 
                     alpha = 0.45) +
    geom_errorbar(data = emmeans_constant_increasing,  # Plot the point estimates in white for background
                  aes(x = trait_type:constant_increasing, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="white",
                  size = 2.5,
                  width = 0.17) +
    geom_point(data = emmeans_constant_increasing,  # Plot the credible intervals in white for background
               aes(x = trait_type:constant_increasing, 
                   y = emmean),
               shape = 21,
               size = 4, 
               stroke = 2,
               color="white",
               fill = "white") +
    geom_errorbar(data = emmeans_constant_increasing, # Plot the point estimates 
                  aes(x = trait_type:constant_increasing, 
                      ymin = lower.HPD, 
                      ymax = upper.HPD), 
                  color="black",
                  size = 2,
                  width = 0.15) +
    geom_point(data = emmeans_constant_increasing, # Plot the credible intervals
               aes(x = trait_type:constant_increasing, 
                   y = emmean),
               shape = 21,
               size = 3.5, 
               stroke = 2,
               color="black",
               fill = "white") +
    geom_text(data = sample_sizes_warm,  # Sample size annotations 
              aes(x = trait_type:constant_increasing, 
                  y = 3.5,
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = constant_increasing), 
              hjust = 1, size = 5, show.legend = FALSE) +
    theme_bw() +     # Customize the plot
    labs(y = "lnVR", x = "") +
    scale_size_continuous(range = c(2, 8))+ 
    scale_fill_manual(values = c("#8E77FF", "#FF6040", "#8E77FF", "#FF6040", "#8E77FF", "#FF6040"))+
    scale_color_manual(values = c("Constant" = "#8E77FF", "Increasing" = "#FF6040")) +  # Text colour
    theme(text = element_text(size = 20, color = "black"),
          legend.title = ggplot2::element_text(size = 16),
          legend.text = ggplot2::element_text(size = 14),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
          panel.border = element_rect(color = "black", size = 1.5)) +
    guides(fill = "none", size = "none")+
    coord_flip() + 
    ylim(-3.5, 3.5)

ggsave(file = "fig/lnVR_constant_increasing.png", width = 12, height = 7, dpi = 500)

Leave-one-out analysis

Model specification

# Get a list of study IDs for the LOO
study_ids <- unique(data$ref)
num_studies <- length(study_ids)

# Initialize a list to store the results
loo_results <- vector("list", num_studies)
names(loo_results) <- study_ids

# Set up parallel processing (16 models at a time)
plan(multisession, workers = 16)  

# Model specification
formula <- bf(lnVR ~ trait_type -1 + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnVR)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant


# Function to fit the model after iteratively removing one study
leave_one_out <- function(study_id) {
  # Subset the data
  data_subset <- subset(data, ref != study_id)
  
  # Recalculate VCV matrix
  VCV_lnVR_subset <- vcalc(
    vi = var_lnVR,
    cluster = shared_control_ID, 
    rho = 0.5,
    obs = obs,
    data = data_subset
  )
  
  # Fit the model
  model_subset <- brm(
    formula, 
    family = gaussian(),
    data = data_subset, 
    data2 = list(
      phylo_matrix = phylo_matrix,
      VCV_lnVR = VCV_lnVR_subset
    ),
    prior = prior,
    control = list(adapt_delta = 0.99, max_treedepth = 15),
    iter = 2000, # Reduce to 2000 iterations to reduce computational demands
    warmup = 1000, 
    chains = 2, # Only two chains to reduce computational demands
    cores = 1,   # Set cores to 1 inside the function
    seed = 123
  )

  # Extract the fixed effects
  fixed_effects <- fixef(model_subset)
  
  # Return the fixed effects
  return(list(study_id = study_id, fixed_effects = fixed_effects))
}

# Run the function in parallel over the studies
loo_results <- future_lapply(study_ids, leave_one_out)

# Save results
saveRDS(loo_results, file = "RData/lnVR_LOO_results.rds")

Model summary

# Load the list of all model outputs
loo_lnVR <- readRDS(file = "RData/lnVR_LOO_results.rds")

# Extract data on fixed effects from each model

loo_results_lnVR <- do.call(rbind, lapply(loo_lnVR, function(x) {
    # Extract study_id and fixed_effects data
    study_id <- x$study_id
    fixed_effects <- x$fixed_effects

    # Convert row names (trait_type) to a column, remove prefix, and add
    # study_id
    fixed_effects <- data.frame(trait_type = sub("trait_type", "", rownames(fixed_effects)),
        fixed_effects)
    fixed_effects$study_id <- study_id

    # Remove row names
    rownames(fixed_effects) <- NULL

    return(fixed_effects)
}))

loo_results_lnVR$trait_type <- factor(loo_results_lnVR$trait_type, levels = c("body_size",
    "fecundity", "survival"), labels = c("Body size", "Fecundity", "Survival"))

# Summarise the data
loo_results_lnVR %>%
    group_by(trait_type) %>%
    summarise(Estimate = mean(Estimate), SE = mean(Est.Error), lower_CI = mean(Q2.5),
        upper_CI = mean(Q97.5))  # Mean across all models
## # A tibble: 3 × 5
##   trait_type Estimate     SE lower_CI upper_CI
##   <fct>         <dbl>  <dbl>    <dbl>    <dbl>
## 1 Body size    0.0272 0.104    -0.172    0.242
## 2 Fecundity   -0.0576 0.0994   -0.254    0.143
## 3 Survival     0.105  0.129    -0.144    0.364

Data visualisation

# Plot
ggplot() +
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75, 
               lwd=1) +
    geom_errorbar(data = loo_results_lnVR,  # Plot the credible intervals in white for background
               aes(x = study_id, 
                   y = Estimate,
                   ymin = Q2.5, 
                   ymax = Q97.5,
                   color = trait_type),
               shape = 21,
               size = 1,
               width = 0.3) +
    geom_point(data = loo_results_lnVR,
               aes(x = study_id, 
                   y = Estimate,
                   fill = trait_type),
               shape = 21,
               size = 4, 
               stroke = 1,
               color="black") +
    theme_bw() +     # Customize the plot
    labs(y = "lnVR", x = "") +
    scale_fill_manual(values = c("#73B706", "#06A2BA", "#B90674"))+
    scale_color_manual(values = c("#73B706", "#06A2BA", "#B90674")) +  
    theme(text = element_text(size = 20, color = "black"),
          legend.title = ggplot2::element_text(size = 16),
          legend.text = ggplot2::element_text(size = 14),
          axis.text.y = ggplot2::element_text(size = 10, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
          panel.border = element_rect(color = "black", size = 1.5),
          strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 20)) +
    guides(fill = "none", color = "none")+
    coord_flip()+
    xlim(-0.45, 0.45) +
    facet_wrap(~trait_type, ncol = 3)+
   scale_x_discrete(limits = rev(levels(as.factor(loo_results_lnVR$study_id)))) # Alphabetical order

ggsave(file = "fig/lnVR_LOO.png", width = 12, height = 12, dpi = 500)

Unusual study designs

Model specification

# Discard observations flagged because the number of generations of selection was unclear, as this would only affect the results of meta-regressions
data <- mutate(data, minor_concerns2 = ifelse(minor_concerns == "gen_selection approximate" | 
                                               minor_concerns == "gen_selection underestimated",
                     NA, minor_concerns))  

# Filter to data without sources of procedural  concerns.
data_concerns <- filter(data, is.na(major_concerns)==T & is.na(minor_concerns2)==T)

# Drop tips that are not in the warm dataset
tips_to_drop <- setdiff(phylo_tree$tip.label, data_concerns$phylogeny)
phylo_tree_concerns <- drop.tip(phylo_tree, tips_to_drop)

# Compute phylogenetic correlation matrix
phylo_matrix_concerns <- vcv(phylo_tree_concerns, cor = T)  # The vcv function returns a variance-covariance matrix

# Convert tibble to data frame
data_concerns <- as.data.frame(data_concerns)

# Calculate VCV matrix
VCV_lnVR_concerns <- vcalc(vi = var_lnVR,
                       cluster = shared_control_ID, 
                       rho = 0.5,
                       obs = obs,
                       data = data_concerns) 

# Model specification
formula <- bf(lnVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + # Separate effects by trait type
                (trait_type-1|ref) + # Correlation between traits among studies
                (1|species) + # Species-level random effect
                (1|gr(phylogeny, cov = phylo_matrix_concerns)) + # Phylogenetic relatedness
                (1|experiment_ID) + # Experiment-level random effect
                (1|obs) + # Observation-level random effect
                fcor(VCV_lnVR_concerns)) # Variance covariance matix of correlated sampling variances

# Define priors
prior = c(
  prior(constant(1), class = "sigma")
) # Because the residual variance-covariance structure is specified in fcor, there is no need to estimate sigma so it is left as a constant

# Fit model
lnVR_model_concerns <- brm(formula, 
                                      family = gaussian(),
                                      data = data_concerns, 
                                      data2 = list(phylo_matrix_concerns = phylo_matrix_concerns,
                                                   VCV_lnVR_concerns = VCV_lnVR_concerns),
                                      prior = prior,
                                      control = list(adapt_delta = 0.99, max_treedepth = 15),
                                      iter = 4000, 
                                      warmup = 2000,
                                      chains = 4, 
                                      cores = 4, 
                                      seed = 123) 
# Save model
saveRDS(lnVR_model_concerns, file = "RData/lnVR_model_concerns.rds")

Model summary

# Load model
lnVR_model_concerns <- readRDS("RData/lnVR_model_concerns.rds")

# Display model output
summary(lnVR_model_concerns)
##  Family: gaussian 
##   Links: mu = identity; sigma = identity 
## Formula: lnVR ~ 0 + trait_type:warm_cold + trait_type:warm_cold:assay_temp_diff + (trait_type - 1 | ref) + (1 | species) + (1 | gr(phylogeny, cov = phylo_matrix_concerns)) + (1 | experiment_ID) + (1 | obs) + fcor(VCV_lnVR_concerns) 
##    Data: data_concerns (Number of observations: 321) 
##   Draws: 4 chains, each with iter = 4000; warmup = 2000; thin = 1;
##          total post-warmup draws = 8000
## 
## Multilevel Hyperparameters:
## ~experiment_ID (Number of levels: 72) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.16      0.08     0.01     0.33 1.00      878     2212
## 
## ~obs (Number of levels: 321) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.78      0.05     0.70     0.88 1.00     2869     5068
## 
## ~phylogeny (Number of levels: 22) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.12      0.10     0.00     0.36 1.00     3156     4492
## 
## ~ref (Number of levels: 33) 
##                                              Estimate Est.Error l-95% CI
## sd(trait_typebody_size)                          0.10      0.08     0.00
## sd(trait_typefecundity)                          0.11      0.09     0.00
## sd(trait_typesurvival)                           0.35      0.19     0.03
## cor(trait_typebody_size,trait_typefecundity)     0.03      0.50    -0.87
## cor(trait_typebody_size,trait_typesurvival)     -0.04      0.50    -0.89
## cor(trait_typefecundity,trait_typesurvival)     -0.02      0.49    -0.87
##                                              u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(trait_typebody_size)                          0.31 1.00     2375     4175
## sd(trait_typefecundity)                          0.33 1.00     2540     4109
## sd(trait_typesurvival)                           0.77 1.00     1561     2855
## cor(trait_typebody_size,trait_typefecundity)     0.89 1.00     5445     5433
## cor(trait_typebody_size,trait_typesurvival)      0.87 1.00     2578     4513
## cor(trait_typefecundity,trait_typesurvival)      0.87 1.00     3091     5346
## 
## ~species (Number of levels: 22) 
##               Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sd(Intercept)     0.08      0.06     0.00     0.24 1.00     3266     4264
## 
## Regression Coefficients:
##                                                   Estimate Est.Error l-95% CI
## trait_typebody_size:warm_coldcold                     0.08      0.22    -0.35
## trait_typefecundity:warm_coldcold                    -0.65      0.37    -1.38
## trait_typesurvival:warm_coldcold                      0.12      0.60    -1.06
## trait_typebody_size:warm_coldwarm                    -0.01      0.16    -0.32
## trait_typefecundity:warm_coldwarm                    -0.12      0.15    -0.40
## trait_typesurvival:warm_coldwarm                      0.22      0.20    -0.18
## trait_typebody_size:warm_coldcold:assay_temp_diff    -0.05      0.07    -0.18
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.23      0.07    -0.37
## trait_typesurvival:warm_coldcold:assay_temp_diff     -0.01      0.15    -0.30
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.02      0.03    -0.04
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.02      0.02    -0.02
## trait_typesurvival:warm_coldwarm:assay_temp_diff     -0.03      0.03    -0.09
##                                                   u-95% CI Rhat Bulk_ESS
## trait_typebody_size:warm_coldcold                     0.52 1.00     3479
## trait_typefecundity:warm_coldcold                     0.07 1.00     5110
## trait_typesurvival:warm_coldcold                      1.29 1.00     6476
## trait_typebody_size:warm_coldwarm                     0.32 1.00     3018
## trait_typefecundity:warm_coldwarm                     0.17 1.00     3178
## trait_typesurvival:warm_coldwarm                      0.63 1.00     4401
## trait_typebody_size:warm_coldcold:assay_temp_diff     0.08 1.00     4979
## trait_typefecundity:warm_coldcold:assay_temp_diff    -0.08 1.00     5770
## trait_typesurvival:warm_coldcold:assay_temp_diff      0.27 1.00     9420
## trait_typebody_size:warm_coldwarm:assay_temp_diff     0.08 1.00     3242
## trait_typefecundity:warm_coldwarm:assay_temp_diff     0.06 1.00     3196
## trait_typesurvival:warm_coldwarm:assay_temp_diff      0.03 1.00     4146
##                                                   Tail_ESS
## trait_typebody_size:warm_coldcold                     4800
## trait_typefecundity:warm_coldcold                     5892
## trait_typesurvival:warm_coldcold                      5805
## trait_typebody_size:warm_coldwarm                     4076
## trait_typefecundity:warm_coldwarm                     4249
## trait_typesurvival:warm_coldwarm                      4377
## trait_typebody_size:warm_coldcold:assay_temp_diff     5687
## trait_typefecundity:warm_coldcold:assay_temp_diff     5867
## trait_typesurvival:warm_coldcold:assay_temp_diff      6624
## trait_typebody_size:warm_coldwarm:assay_temp_diff     4646
## trait_typefecundity:warm_coldwarm:assay_temp_diff     4575
## trait_typesurvival:warm_coldwarm:assay_temp_diff      5704
## 
## Further Distributional Parameters:
##       Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma     1.00      0.00     1.00     1.00   NA       NA       NA
## 
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
# Cleaned model output
as.data.frame(fixef(lnVR_model_concerns, summary = TRUE)) %>%
    # Rename categorical variables for cleaner display
rownames_to_column(var = "Parameter") %>%
    mutate(Parameter = gsub("trait_type([a-z_]+):warm_cold(cold|warm)", "\\1(\\2)",
        Parameter), Parameter = gsub("trait_type([a-z_]+)\\(warm\\):assay_temp_diff",
        "\\1(warm): assay_temp_diff", Parameter)) %>%
    # Round numbers to 3 decimal points
mutate(across(c(Estimate, Q2.5, Q97.5), ~round(., 3))) %>%
    select(Parameter, Estimate, `Lower CI` = Q2.5, `Upper CI` = Q97.5) %>%
    kable() %>%
    kable_styling(full_width = FALSE, position = "center", fixed_thead = TRUE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE) %>%
    row_spec(0, background = "white", color = "black", bold = TRUE) %>%
    kable_styling(fixed_thead = TRUE)
Parameter Estimate Lower CI Upper CI
body_size(cold) 0.081 -0.346 0.518
fecundity(cold) -0.649 -1.378 0.069
survival(cold) 0.118 -1.058 1.292
body_size(warm) -0.007 -0.321 0.320
fecundity(warm) -0.116 -0.401 0.171
survival(warm) 0.215 -0.176 0.625
body_size(cold):assay_temp_diff -0.047 -0.179 0.084
fecundity(cold):assay_temp_diff -0.227 -0.370 -0.081
survival(cold):assay_temp_diff -0.009 -0.300 0.273
body_size(warm):assay_temp_diff 0.018 -0.040 0.075
fecundity(warm):assay_temp_diff 0.020 -0.019 0.059
survival(warm):assay_temp_diff -0.028 -0.090 0.034

Data visualisation

# Discard observations flagged because the number of generations of selection was unclear, as this would only affect the results of meta-regressions
data <- mutate(data, minor_concerns2 = ifelse(minor_concerns == "gen_selection approximate" | 
                                               minor_concerns == "gen_selection underestimated",
                     NA, minor_concerns)) 

# Filter to data without sources of procedural  concerns.
data_concerns <- filter(data, is.na(major_concerns)==T & is.na(minor_concerns2)==T)

# Calculate sample sizes and study counts
sample_sizes_concerns <- data_concerns %>%
  group_by(trait_type, warm_cold) %>%
  summarise(
    estimates = n(),
    studies = n_distinct(ref)
  )

# Generate predictions
emmeans_concerns <- as.data.frame(emmeans(
  lnVR_model_concerns,
  specs = ~ assay_temp_diff | trait_type * warm_cold,
  at = list(assay_temp_diff = seq(min(data_concerns$assay_temp_diff), max(data_concerns$assay_temp_diff), by = 0.5))))

# Calculate range of values for each category
range_df_concerns <- data_concerns %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_assay_temp_diff = min(assay_temp_diff),
    max_assay_temp_diff = max(assay_temp_diff)
  )

emmeans_concerns$trait_type <- factor(emmeans_concerns$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_concerns$warm_cold <- factor(emmeans_concerns$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_concerns <- emmeans_concerns %>%
  left_join(range_df_concerns, by = c("trait_type", "warm_cold")) %>%
  filter(
    assay_temp_diff >= min_assay_temp_diff,
    assay_temp_diff <= max_assay_temp_diff
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) +  
    geom_vline(xintercept = 0, # Vertical line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data_concerns, # Effect sizes, scaled by precision
                  aes(x = assay_temp_diff, 
                      y = lnVR, 
                      size = 1/sqrt(var_lnVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_concerns, # Shaded area for credible intervals
                 aes(x = assay_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_concerns,  # Predicted regression line
               aes(y = emmean,
                   x = assay_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) + 
    geom_text(data = sample_sizes_concerns, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  
  facet_wrap(~ trait_type, ncol = 1) + # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Assay temperature difference", y = "lnVR",
       col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3.5, 3.5))

ggsave(file = "fig/lnVR_concerns.png", width = 12, height = 7, dpi = 500)

Figures for publication

Note that Figure 1 was created without code.

Figure 2

# Match species to the OTL database
resolved_names <- tnrs_match_names(unique(data$species), context_name = "Animals")

# Create tree
tree <- tol_induced_subtree(ott_ids = resolved_names$ott_id)
tree$tip.label <- strip_ott_ids(tree$tip.label) # Remove ott IDs for presentation

tree <- multi2di(tree, random = TRUE) # Resolve polytomy at random, but it matches classification from Cornetti et al. 2019. Molecular Phylogenetics and Evolution; with D. pulex and D. pulicaria being more closely related to eachother than D. magna
phylo_tree <- compute.brlen(tree, method = "Grafen", power = 1) # Compute branch lengths

# Remove underscore for species names
phylo_tree$tip.label <- gsub("_", " ", phylo_tree$tip.label) # Add underscore between species names

# Create a data summary for each species
species_summary <- data %>%
  group_by(tip.label = species, warm_cold) %>%
  summarise(n_effect_sizes = n(), .groups = "drop") 

species_totals <- species_summary %>%
  group_by(tip.label) %>%
  summarise(total_effect_sizes = sum(n_effect_sizes), .groups = "drop")

# Order species
species_order <- rev(c(
  "Drosophila bipectinata",
  "Drosophila pseudoananassae",
  "Drosophila melanogaster",
  "Drosophila serrata",
  "Drosophila subobscura",
  "Drosophila hydei",
  "Drosophila buzzatii",
  "Musca domestica",
  "Sepsis punctum",
  "Callosobruchus chinensis",
  "Callosobruchus maculatus",
  "Zabrotes subfasciatus",
  "Tribolium castaneum",
  "Daphnia pulicaria",
  "Daphnia pulex",
  "Daphnia magna",
  "Simocephalus vetulus",
  "Apocyclops royi",
  "Eurytemora affinis",
  "Rhizoglyphus robini",
  "Caenorhabditis remanei",
  "Ophryotrocha labronica",
  "Brachionus plicatilis",
  "Poecilia reticulata",
  "Danio rerio"
))

species_summary <- species_summary %>%
  mutate(tip.label = factor(tip.label, levels = species_order))

# Plot tree
tree_plot <- ggtree(phylo_tree, lwd = 1.25) +
  geom_tiplab(size = 5,
              offset = 0.075,
              fontface = "italic") + 
  xlim(0, 2.5) + 
  theme(plot.margin = unit(c(0, 1.5, 0, 0), "cm"))

barplot <- ggplot(species_summary, aes(x = tip.label, 
                                       y = n_effect_sizes, 
                                       fill = warm_cold)) +
  geom_bar(stat = "identity", 
           position = position_dodge2(), 
           width = 0.8) +
  geom_hline(yintercept = 0, 
             color = "black", 
             size = 0.75) +  # Add vertical line
  geom_vline(xintercept = 0.4, 
             color = "black", 
             size = 0.5) +  # Add horizontal line
  geom_text(data = species_totals, 
            aes(x = tip.label, 
                y = -8, 
                label = total_effect_sizes), 
            inherit.aes = FALSE, 
            size = 5) +  # Add total count annotation
  scale_fill_manual(values = c("Cold" = "#06B4BA", "Warm" = "#E80756")) +
  coord_flip() +
  scale_y_continuous(expand = expansion(mult = c(0.05, 0.2))) +  # Add space on the right
  theme_minimal() +
  labs(x = NULL, y = "Number of effect sizes") +
  theme(axis.text.y = element_blank(),  # Remove y-axis text for alignment
        axis.ticks.y = element_blank(),
        panel.grid = element_blank(),  # Remove grid
        plot.background = element_rect(fill = "white", color = NA),  # White background
        legend.position = "none",
        axis.text = element_text (size = 14), col = "black",
        axis.title = element_text(size = 18))


tree_plot | barplot

ggsave(file = "fig/figure_2.png", width = 12, height = 10, dpi = 500)

Figure 3

# Load model
lnRR_model_assay_temp_diff <- readRDS("RData/lnRR_model_assay_temp_diff.rds")

# Generate predictions
emmeans_assay_temp_diff <- as.data.frame(emmeans(
  lnRR_model_assay_temp_diff,
  specs = ~ assay_temp_diff | trait_type * warm_cold,
  at = list(assay_temp_diff = seq(min(data$assay_temp_diff), max(data$assay_temp_diff), by = 0.5)))
  )

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_assay_temp_diff = min(assay_temp_diff),
    max_assay_temp_diff = max(assay_temp_diff)
  )

emmeans_assay_temp_diff$trait_type <- factor(emmeans_assay_temp_diff$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_assay_temp_diff$warm_cold <- factor(emmeans_assay_temp_diff$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_assay_temp_diff <- emmeans_assay_temp_diff %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    assay_temp_diff >= min_assay_temp_diff,
    assay_temp_diff <= max_assay_temp_diff
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) +  
    geom_vline(xintercept = 0, # Vertical line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) +  
    geom_point(data = data, # Effect sizes, scaled by precision
                  aes(x = assay_temp_diff, 
                      y = lnRR, 
                      size = 1/sqrt(var_lnRR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_assay_temp_diff, # Shaded area for credible intervals
                 aes(x = assay_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_assay_temp_diff,  # Predicted regression line
               aes(y = emmean,
                   x = assay_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) + 
      geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -0.9, -1.3),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  
  facet_wrap(~ trait_type, ncol = 1) + # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Assay temperature difference", y = "lnRR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(4, 10))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-1.5, 1.5))

ggsave(file = "fig/figure_3.png", width = 12, height = 10, dpi = 500)

Figure 4

# Load models
lnRR_model_sel_temp_diff <- readRDS("RData/lnRR_model_sel_temp_diff.rds")
lnRR_model_gen_selection <- readRDS("RData/lnRR_model_gen_selection.rds")
lnRR_model_gen_common_garden <- readRDS("RData/lnRR_model_gen_common_garden.rds")
lnRR_model_pop_size <- readRDS("RData/lnRR_model_pop_size.rds")
lnRR_model_all_moderators <- readRDS("RData/lnRR_model_all_moderators.rds")

##################### Selection temperature ################################

# Generate predictions
emmeans_sel_temp_diff <- as.data.frame(emmeans(
  lnRR_model_sel_temp_diff,
  specs = ~ select_temp_diff | trait_type * warm_cold,
  at = list(select_temp_diff = seq(min(data$select_temp_diff), max(data$select_temp_diff), by = 0.1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_select_temp_diff = min(select_temp_diff),
    max_select_temp_diff = max(select_temp_diff)
  )

emmeans_sel_temp_diff$trait_type <- factor(emmeans_sel_temp_diff$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_sel_temp_diff$warm_cold <- factor(emmeans_sel_temp_diff$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_sel_temp_diff <- emmeans_sel_temp_diff %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    select_temp_diff >= min_select_temp_diff,
    select_temp_diff <= max_select_temp_diff
  )

# Plot
sel_temp_diff <- 
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = select_temp_diff, 
                      y = lnRR, 
                      size = 1/sqrt(var_lnRR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_sel_temp_diff, # Shaded area for credible intervals
                 aes(x = select_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_sel_temp_diff, # Predicted regression line
               aes(y = emmean,
                   x = select_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -0.9, -1.3),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Selection temperature difference", y = "lnRR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(4, 10))+ 
  theme(text = element_text(size = 30, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 28),
        plot.margin = unit(c(1, 0, 0, 0), "cm")) +
    guides(fill = "none", size = "none", color = "none")+
    coord_cartesian(ylim = c(-1.5, 1.5))

############## Generations of selection ##################################

# Generate predictions
emmeans_gen_selection <- as.data.frame(emmeans(
  lnRR_model_gen_selection,
  specs = ~ gen_selection | trait_type * warm_cold,
  at = list(gen_selection = seq(min(data$gen_selection), max(data$gen_selection), by = 1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_gen_selection = min(gen_selection),
    max_gen_selection = max(gen_selection)
  )

emmeans_gen_selection$trait_type <- factor(emmeans_gen_selection$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_gen_selection$warm_cold <- factor(emmeans_gen_selection$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_gen_selection <- emmeans_gen_selection %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    gen_selection >= min_gen_selection,
    gen_selection <= max_gen_selection
  )

# Plot
gen_selection <- 
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = gen_selection, 
                      y = lnRR, 
                      size = 1/sqrt(var_lnRR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_gen_selection, # Shaded area for credible intervals
                 aes(x = gen_selection,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_gen_selection, # Predicted regression line
               aes(y = emmean,
                   x = gen_selection,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -0.9, -1.3),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Number  of generations of selection", y = "lnRR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(4, 10))+ 
  theme(text = element_text(size = 30, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 28),
        plot.margin = unit(c(1.5, 0, 0, 0), "cm")) +
    guides(fill = "none", size = "none", color = "none")+
    coord_cartesian(ylim = c(-1.5, 1.5),
                    xlim = c(0, 150))


################### Generations of common garden #################################

# Generate predictions
emmeans_gen_common_garden <- as.data.frame(emmeans(
  lnRR_model_gen_common_garden,
  specs = ~ gen_common_garden | trait_type * warm_cold,
  at = list(gen_common_garden = seq(min(data$gen_common_garden), max(data$gen_common_garden), by = 1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_gen_common_garden = min(gen_common_garden),
    max_gen_common_garden = max(gen_common_garden)
  )

emmeans_gen_common_garden$trait_type <- factor(emmeans_gen_common_garden$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_gen_common_garden$warm_cold <- factor(emmeans_gen_common_garden$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_gen_common_garden <- emmeans_gen_common_garden %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    gen_common_garden >= min_gen_common_garden,
    gen_common_garden <= max_gen_common_garden
  )

# Plot
gen_common_garden <- 
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = gen_common_garden, 
                      y = lnRR, 
                      size = 1/sqrt(var_lnRR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_gen_common_garden, # Shaded area for credible intervals
                 aes(x = gen_common_garden,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_gen_common_garden, # Predicted regression line
               aes(y = emmean,
                   x = gen_common_garden,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -0.9, -1.3),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Number of generations of common garden", y = "", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(4, 10))+ 
  theme(text = element_text(size = 30, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 28),
        plot.margin = unit(c(1.5, 1, 0, 0.5), "cm")) +
    guides(fill = "none", size = "none", color = "none")+
    coord_cartesian(ylim = c(-1.5, 1.5),
                    xlim = c(0, 11.5))

##################### Initial population size ##################################

# Generate predictions
emmeans_pop_size <- as.data.frame(emmeans(
  lnRR_model_pop_size,
  specs = ~ pop_size | trait_type * warm_cold,
  at = list(pop_size = seq(min(data$pop_size, na.rm=T), max(data$pop_size, na.rm=T), by = 50),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_pop_size = min(pop_size, na.rm=T),
    max_pop_size = max(pop_size, na.rm=T)
  )

emmeans_pop_size$trait_type <- factor(emmeans_pop_size$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_pop_size$warm_cold <- factor(emmeans_pop_size$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_pop_size <- emmeans_pop_size %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    pop_size >= min_pop_size,
    pop_size <= max_pop_size
  )

# Calculate sample sizes and study counts for population size
sample_sizes_pop_size <- data %>%
  filter(is.na(pop_size)==FALSE) %>% 
  group_by(trait_type, warm_cold) %>%
  summarise(
    estimates = n(),
    studies = n_distinct(ref)
  )

# Plot
pop_size <- 
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = pop_size, 
                      y = lnRR, 
                      size = 1/sqrt(var_lnRR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_pop_size, # Shaded area for credible intervals
                 aes(x = pop_size,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_pop_size, # Predicted regression line
               aes(y = emmean,
                   x = pop_size,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes_pop_size, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -0.9, -1.3),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Population size", y = "", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(4, 10))+ 
  theme(text = element_text(size = 30, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 28),
        plot.margin = unit(c(0, 1, 0, 0.5), "cm")) +
    guides(fill = "none", size = "none", color = "none")+
    coord_cartesian(ylim = c(-1.5, 1.5))

##################### Full model ##################################

# Generate predictions at the mean of each moderator
emmeans_full_model <- as.data.frame(emmeans(
  lnRR_model_all_moderators,
  specs = ~ assay_temp_diff * select_temp_diff * gen_selection * gen_common_garden | trait_type * warm_cold,
   at = list(assay_temp_diff = seq(min(data$assay_temp_diff), max(data$assay_temp_diff), by = 0.5)))) 


# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_assay_temp_diff = min(assay_temp_diff),
    max_assay_temp_diff = max(assay_temp_diff)
  )

emmeans_full_model$trait_type <- factor(emmeans_full_model$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_full_model$warm_cold <- factor(emmeans_full_model$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_full_model <- emmeans_full_model%>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    assay_temp_diff >= min_assay_temp_diff,
    assay_temp_diff <= max_assay_temp_diff
  )

# Plot
assay_temp <-
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) +  
    geom_vline(xintercept = 0, # Vertical line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data, # Effect sizes, scaled by precision
                  aes(x = assay_temp_diff, 
                      y = lnRR, 
                      size = 1/sqrt(var_lnRR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_full_model, # Shaded area for credible intervals
                 aes(x = assay_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_full_model,  # Predicted regression line
               aes(y = emmean,
                   x = assay_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) + 
    geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  
  facet_wrap(~ trait_type, ncol = 1) + # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Assay temperature difference", y = "lnRR",
       col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(4, 10))+ 
  theme(text = element_text(size = 30, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 28)) +
    guides(fill = "none", size = "none", col = "none")+
    coord_cartesian(ylim = c(-1.5, 1.5))


assay_temp / (sel_temp_diff | pop_size) / (gen_selection | gen_common_garden)

ggsave(file = "fig/figure_4.png", width = 20, height = 32, dpi = 500)

Figure 5

# Load model
lnVR_model_assay_temp_diff <- readRDS("RData/lnVR_model_assay_temp_diff.rds")

# Generate predictions
emmeans_assay_temp_diff <- as.data.frame(emmeans(
  lnVR_model_assay_temp_diff,
  specs = ~ assay_temp_diff | trait_type * warm_cold,
  at = list(assay_temp_diff = seq(min(data$assay_temp_diff), max(data$assay_temp_diff), by = 0.5)))
  )

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_assay_temp_diff = min(assay_temp_diff),
    max_assay_temp_diff = max(assay_temp_diff)
  )

emmeans_assay_temp_diff$trait_type <- factor(emmeans_assay_temp_diff$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_assay_temp_diff$warm_cold <- factor(emmeans_assay_temp_diff$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_assay_temp_diff <- emmeans_assay_temp_diff %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    assay_temp_diff >= min_assay_temp_diff,
    assay_temp_diff <= max_assay_temp_diff
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) +  
    geom_vline(xintercept = 0, # Vertical line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data, # Effect sizes, scaled by precision
                  aes(x = assay_temp_diff, 
                      y = lnVR, 
                      size = 1/sqrt(var_lnVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_assay_temp_diff, # Shaded area for credible intervals
                 aes(x = assay_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_assay_temp_diff,  # Predicted regression line
               aes(y = emmean,
                   x = assay_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) + 
    geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  
  facet_wrap(~ trait_type, ncol = 1) + # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Assay temperature difference", y = "lnVR",
       col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 25, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 22)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3.5, 3.5))

ggsave(file = "fig/figure_5.png", width = 12, height = 10, dpi = 500)

Figure 6

# Load models
lnVR_model_sel_temp_diff <- readRDS("RData/lnVR_model_sel_temp_diff.rds")
lnVR_model_gen_selection <- readRDS("RData/lnVR_model_gen_selection.rds")
lnVR_model_gen_common_garden <- readRDS("RData/lnVR_model_gen_common_garden.rds")
lnVR_model_pop_size <- readRDS("RData/lnVR_model_pop_size.rds")
lnVR_model_all_moderators <- readRDS("RData/lnVR_model_all_moderators.rds")

##################### Selection temperature ################################

# Generate predictions
emmeans_sel_temp_diff <- as.data.frame(emmeans(
  lnVR_model_sel_temp_diff,
  specs = ~ select_temp_diff | trait_type * warm_cold,
  at = list(select_temp_diff = seq(min(data$select_temp_diff), max(data$select_temp_diff), by = 0.1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_select_temp_diff = min(select_temp_diff),
    max_select_temp_diff = max(select_temp_diff)
  )

emmeans_sel_temp_diff$trait_type <- factor(emmeans_sel_temp_diff$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_sel_temp_diff$warm_cold <- factor(emmeans_sel_temp_diff$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_sel_temp_diff <- emmeans_sel_temp_diff %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    select_temp_diff >= min_select_temp_diff,
    select_temp_diff <= max_select_temp_diff
  )

# Plot
sel_temp_diff <- 
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = select_temp_diff, 
                      y = lnVR, 
                      size = 1/sqrt(var_lnVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_sel_temp_diff, # Shaded area for credible intervals
                 aes(x = select_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_sel_temp_diff, # Predicted regression line
               aes(y = emmean,
                   x = select_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Selection temperature difference", y = "lnVR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
 theme(text = element_text(size = 30, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 28),
        plot.margin = unit(c(1, 0, 0, 0), "cm")) +
    guides(fill = "none", size = "none", color = "none")+
    coord_cartesian(ylim = c(-3.5, 3.5))

############## Generations of selection ##################################

# Generate predictions
emmeans_gen_selection <- as.data.frame(emmeans(
  lnVR_model_gen_selection,
  specs = ~ gen_selection | trait_type * warm_cold,
  at = list(gen_selection = seq(min(data$gen_selection), max(data$gen_selection), by = 1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_gen_selection = min(gen_selection),
    max_gen_selection = max(gen_selection)
  )

emmeans_gen_selection$trait_type <- factor(emmeans_gen_selection$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_gen_selection$warm_cold <- factor(emmeans_gen_selection$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_gen_selection <- emmeans_gen_selection %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    gen_selection >= min_gen_selection,
    gen_selection <= max_gen_selection
  )

# Plot
gen_selection <- 
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = gen_selection, 
                      y = lnVR, 
                      size = 1/sqrt(var_lnVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_gen_selection, # Shaded area for credible intervals
                 aes(x = gen_selection,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_gen_selection, # Predicted regression line
               aes(y = emmean,
                   x = gen_selection,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Number  of generations of selection", y = "lnRR", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 30, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 28),
        plot.margin = unit(c(1.5, 0, 0, 0), "cm")) +
    guides(fill = "none", size = "none", color = "none")+
    coord_cartesian(ylim = c(-3.5, 3.5),
                    xlim = c(0, 150))

################### Generations of common garden #################################

# Generate predictions
emmeans_gen_common_garden <- as.data.frame(emmeans(
  lnVR_model_gen_common_garden,
  specs = ~ gen_common_garden | trait_type * warm_cold,
  at = list(gen_common_garden = seq(min(data$gen_common_garden), max(data$gen_common_garden), by = 1),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_gen_common_garden = min(gen_common_garden),
    max_gen_common_garden = max(gen_common_garden)
  )

emmeans_gen_common_garden$trait_type <- factor(emmeans_gen_common_garden$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_gen_common_garden$warm_cold <- factor(emmeans_gen_common_garden$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_gen_common_garden <- emmeans_gen_common_garden %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    gen_common_garden >= min_gen_common_garden,
    gen_common_garden <= max_gen_common_garden
  )

# Plot
gen_common_garden <- 
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = gen_common_garden, 
                      y = lnVR, 
                      size = 1/sqrt(var_lnVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_gen_common_garden, # Shaded area for credible intervals
                 aes(x = gen_common_garden,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_gen_common_garden, # Predicted regression line
               aes(y = emmean,
                   x = gen_common_garden,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Number of generations of common garden", y = "", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 30, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 28),
        plot.margin = unit(c(1.5, 1, 0, 0.5), "cm")) +
    guides(fill = "none", size = "none", color = "none")+
    coord_cartesian(ylim = c(-3.5, 3.5),
                    xlim = c(0, 11.5))

##################### Initial population size ##################################

# Generate predictions
emmeans_pop_size <- as.data.frame(emmeans(
  lnVR_model_pop_size,
  specs = ~ pop_size | trait_type * warm_cold,
  at = list(pop_size = seq(min(data$pop_size, na.rm=T), max(data$pop_size, na.rm=T), by = 50),
            assay_temp_diff = 0))
  ) # Conditional effects on assay_temp_diff = 0

# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_pop_size = min(pop_size, na.rm=T),
    max_pop_size = max(pop_size, na.rm=T)
  )

emmeans_pop_size$trait_type <- factor(emmeans_pop_size$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_pop_size$warm_cold <- factor(emmeans_pop_size$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_pop_size <- emmeans_pop_size %>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    pop_size >= min_pop_size,
    pop_size <= max_pop_size
  )

# Calculate sample sizes and study counts for population size
sample_sizes_pop_size <- data %>%
  filter(is.na(pop_size)==FALSE) %>% 
  group_by(trait_type, warm_cold) %>%
  summarise(
    estimates = n(),
    studies = n_distinct(ref)
  )

# Plot
pop_size <- 
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data,  # Effect sizes, scaled by precision
                  aes(x = pop_size, 
                      y = lnVR, 
                      size = 1/sqrt(var_lnVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_pop_size, # Shaded area for credible intervals
                 aes(x = pop_size,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_pop_size, # Predicted regression line
               aes(y = emmean,
                   x = pop_size,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) +  
     geom_text(data = sample_sizes_pop_size, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  facet_wrap(~ trait_type, ncol = 1) +  # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Population size", y = "", col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 30, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 28),
        plot.margin = unit(c(0, 1, 0, 0.5), "cm")) +
    guides(fill = "none", size = "none", color = "none")+
    coord_cartesian(ylim = c(-3.5, 3.5))

##################### Full model  ##################################

# Generate predictions at the mean of each moderator
emmeans_full_model <- as.data.frame(emmeans(
  lnVR_model_all_moderators,
  specs = ~ assay_temp_diff * select_temp_diff * gen_selection * gen_common_garden | trait_type * warm_cold,
   at = list(assay_temp_diff = seq(min(data$assay_temp_diff), max(data$assay_temp_diff), by = 0.5)))) 


# Calculate range of values for each category
range_df <- data %>%
  group_by(trait_type, warm_cold) %>%
  summarize(
    min_assay_temp_diff = min(assay_temp_diff),
    max_assay_temp_diff = max(assay_temp_diff)
  )

emmeans_full_model$trait_type <- factor(emmeans_full_model$trait_type, 
                          levels = c("body_size", "fecundity", "survival"), 
                          labels = c("Body size", "Fecundity", "Survival"))

emmeans_full_model$warm_cold <- factor(emmeans_full_model$warm_cold, 
                          levels = c("cold", "warm"), 
                          labels = c("Cold", "Warm"))

# Tailor predictions to the range of the data
emmeans_full_model <- emmeans_full_model%>%
  left_join(range_df, by = c("trait_type", "warm_cold")) %>%
  filter(
    assay_temp_diff >= min_assay_temp_diff,
    assay_temp_diff <= max_assay_temp_diff
  )

# Plot
ggplot() + 
    geom_hline(yintercept = 0, # Horizontal line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) +  
    geom_vline(xintercept = 0, # Vertical line
               linetype = 2, 
               colour = "black", 
               alpha = 0.75) + 
    geom_point(data = data, # Effect sizes, scaled by precision
                  aes(x = assay_temp_diff, 
                      y = lnVR, 
                      size = 1/sqrt(var_lnVR), 
                      fill = warm_cold), 
                  shape = 21, 
                  alpha = 0.7, 
                  stroke = 1,
                  position = position_jitter(width = 0.05)) + 
     geom_ribbon(data = emmeans_full_model, # Shaded area for credible intervals
                 aes(x = assay_temp_diff,
                     ymin = lower.HPD, 
                     ymax = upper.HPD, 
                     fill = warm_cold,
                     group = warm_cold), 
                 alpha = .5) + 
     geom_line(data = emmeans_full_model,  # Predicted regression line
               aes(y = emmean,
                   x = assay_temp_diff,
                   color = warm_cold,
                   group = warm_cold), 
               size = 1.5) + 
    geom_text(data = sample_sizes, 
              aes(x = Inf, 
                  y = ifelse(warm_cold == "Warm", -2, -2.75),  # Sample sizes
                  label = paste0("k = ", estimates, " (", studies, ")"),
                  color = warm_cold), 
              hjust = 1.05, size = 5, show.legend = FALSE) +
  
  facet_wrap(~ trait_type, ncol = 1) + # Different panels for each trait
  scale_fill_manual(values = c("#06B4BA", "#E80756"))+
  scale_color_manual(values = c("#06B4BA", "#E80756"))+
  labs(x = "Assay temperature difference", y = "lnVR",
       col = "Regime") +
  theme_bw() + 
  scale_size_continuous(range = c(2, 8))+ 
  theme(text = element_text(size = 30, color = "black"),
          legend.title = ggplot2::element_text(size = 18),
          legend.text = ggplot2::element_text(size = 16),
          axis.text.y = ggplot2::element_text(size = 20, 
                colour = "black", hjust = 0.5),
          axis.text.x = ggplot2::element_text(size = 20),
        panel.border = element_rect(color = "black", size = 1.5),
        strip.background = element_blank(),
        strip.text = element_text(color = "black", size = 28)) +
    guides(fill = "none", size = "none")+
    coord_cartesian(ylim = c(-3.5, 3.5))

assay_temp / (sel_temp_diff | pop_size) / (gen_selection | gen_common_garden)

ggsave(file = "fig/figure_6.png", width = 20, height = 32, dpi = 500)

Figure S1

Package information

sessionInfo()
## R version 4.2.0 (2022-04-22 ucrt)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 22631)
## 
## Matrix products: default
## 
## locale:
## [1] LC_COLLATE=English_Australia.utf8  LC_CTYPE=English_Australia.utf8   
## [3] LC_MONETARY=English_Australia.utf8 LC_NUMERIC=C                      
## [5] LC_TIME=English_Australia.utf8    
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] ggtreeExtra_1.7.0   ggtree_3.5.0.901    kableExtra_1.3.4   
##  [4] ggbeeswarm_0.7.2    tidybayes_3.0.6     emmeans_1.7.3      
##  [7] metafor_4.2-0       numDeriv_2016.8-1.1 metadat_1.2-0      
## [10] Matrix_1.5-4        orchaRd_2.0         brms_2.22.0        
## [13] Rcpp_1.0.10         rotl_3.0.14         ape_5.7-1          
## [16] lubridate_1.9.2     forcats_1.0.0       stringr_1.5.0      
## [19] dplyr_1.1.2         purrr_1.0.1         readr_2.1.4        
## [22] tidyr_1.3.0         tibble_3.2.1        ggplot2_3.5.1      
## [25] tidyverse_2.0.0    
## 
## loaded via a namespace (and not attached):
##   [1] backports_1.4.1        systemfonts_1.0.4      plyr_1.8.8            
##   [4] lazyeval_0.2.2         splines_4.2.0          svUnit_1.0.6          
##   [7] rncl_0.8.7             TH.data_1.1-2          rstantools_2.3.1      
##  [10] inline_0.3.19          digest_0.6.31          yulab.utils_0.0.6     
##  [13] htmltools_0.5.5        fansi_1.0.4            magrittr_2.0.3        
##  [16] checkmate_2.2.0        tzdb_0.4.0             RcppParallel_5.1.7    
##  [19] matrixStats_0.63.0     sandwich_3.1-1         svglite_2.1.1         
##  [22] timechange_0.2.0       rmdformats_1.0.4       prettyunits_1.1.1     
##  [25] colorspace_2.1-0       rvest_1.0.3            ggdist_3.2.1          
##  [28] textshaping_0.3.6      xfun_0.39              callr_3.7.3           
##  [31] crayon_1.5.2           jsonlite_1.8.7         survival_3.7-0        
##  [34] zoo_1.8-12             glue_1.6.2             gtable_0.3.4          
##  [37] webshot_0.5.4          V8_6.0.0               distributional_0.3.2  
##  [40] pkgbuild_1.4.2         rstan_2.32.6           rentrez_1.2.3         
##  [43] abind_1.4-5            scales_1.3.0           mvtnorm_1.1-3         
##  [46] viridisLite_0.4.2      xtable_1.8-4           progress_1.2.2        
##  [49] gridGraphics_0.5-1     tidytree_0.4.2         stats4_4.2.0          
##  [52] StanHeaders_2.32.10    httr_1.4.7             arrayhelpers_1.1-0    
##  [55] posterior_1.6.0        pkgconfig_2.0.3        loo_2.8.0             
##  [58] XML_3.99-0.14          farver_2.1.1           sass_0.4.9            
##  [61] utf8_1.2.3             ggplotify_0.1.0        tidyselect_1.2.1      
##  [64] labeling_0.4.3         rlang_1.1.1            reshape2_1.4.4        
##  [67] munsell_0.5.0          tools_4.2.0            cachem_1.0.8          
##  [70] cli_3.6.1              generics_0.1.3         mathjaxr_1.6-0        
##  [73] evaluate_0.21          fastmap_1.1.1          yaml_2.3.7            
##  [76] ragg_1.2.5             processx_3.8.1         knitr_1.44            
##  [79] nlme_3.1-157           formatR_1.14           aplot_0.1.10          
##  [82] xml2_1.3.6             compiler_4.2.0         bayesplot_1.10.0      
##  [85] rstudioapi_0.15.0      beeswarm_0.4.0         curl_5.0.0            
##  [88] treeio_1.21.0          bslib_0.5.1            stringi_1.7.12        
##  [91] highr_0.10             ps_1.7.5               Brobdingnag_1.2-9     
##  [94] lattice_0.20-45        tensorA_0.36.2         vctrs_0.6.2           
##  [97] pillar_1.9.0           lifecycle_1.0.3        jquerylib_0.1.4       
## [100] bridgesampling_1.1-2   estimability_1.3       patchwork_1.2.0.9000  
## [103] QuickJSR_1.3.1         R6_2.5.1               bookdown_0.34         
## [106] gridExtra_2.3          vipor_0.4.5            codetools_0.2-18      
## [109] MASS_7.3-56            withr_2.5.0            multcomp_1.4-26       
## [112] parallel_4.2.0         hms_1.1.3              grid_4.2.0            
## [115] ggfun_0.0.9            coda_0.19-4            rmarkdown_2.25.1      
## [118] ggnewscale_0.4.10.9000
LS0tDQp0aXRsZTogIioqRXZvbHV0aW9uIG9mIHJlcHJvZHVjdGlvbiwgc3Vydml2YWwsIGFuZCBib2R5IHNpemUgaW4gcmVzcG9uc2UgdG8gY2hhbmdpbmcgdGVtcGVyYXR1cmVzKioiDQphdXRob3I6IFBvdHRpZXIgZXQgYWwuDQpkYXRlOiAibGF0ZXN0IHVwZGF0ZTogYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiAlWScpYCINCm91dHB1dDogDQogIHJtZGZvcm1hdHM6OmRvd25jdXRlOg0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICB0b2NfZGVwdGg6IDYNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IGZhbHNlDQogICAgbGlnaHRib3g6IHRydWUNCiAgICB0aHVtYm5haWxzOiBmYWxzZQ0KICAgIGRvd25jdXRlX3RoZW1lOiAiY2hhb3MiDQogICAgY29kZV9vdmVyZmxvdzogd3JhcA0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogY29uc29sZQ0KLS0tDQoNCg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCg0KLyogQWRqdXN0IHRoZSB0aXRsZSBhcmVhICovDQoudGl0bGUgew0KICAgIG1heC13aWR0aDogMTQwJSAhaW1wb3J0YW50Ow0KICAgIHdpZHRoOiAxNDAlICFpbXBvcnRhbnQ7DQp9DQoNCi8qIFBvc2l0aW9uIHRoZSBUT0Mgb24gdGhlIGxlZnQgKi8NCiN0b2Mgew0KICAgIHBvc2l0aW9uOiBmaXhlZCAhaW1wb3J0YW50Ow0KICAgIHRvcDogMCAhaW1wb3J0YW50Ow0KICAgIGxlZnQ6IDEwMHB4ICFpbXBvcnRhbnQ7DQogICAgcmlnaHQ6IC0yMDBweCAhaW1wb3J0YW50Ow0KICAgIG92ZXJmbG93LXk6IGF1dG8gIWltcG9ydGFudDsNCiAgICBwYWRkaW5nLXRvcDogNTBweCAhaW1wb3J0YW50Ow0KICAgIHotaW5kZXg6IDEwMDAgIWltcG9ydGFudDsgDQp9DQoNCi8qIFBvc2l0aW9uIHRoZSB0aGVtZSBzd2l0Y2ggYnV0dG9uIHRvIHRoZSBib3R0b20gbGVmdCAqLw0KLmRhcmstdGhlbWUtdG9nZ2xlciB7DQogICAgcG9zaXRpb246IGZpeGVkICFpbXBvcnRhbnQ7DQogICAgYm90dG9tOiAtMTUwcHggIWltcG9ydGFudDsgDQogICAgbGVmdDogMTAwcHggIWltcG9ydGFudDsgIA0KICAgIHotaW5kZXg6IDUwMCAhaW1wb3J0YW50OyANCn0NCg0KLyogQWRqdXN0IHRoZSBtYWluIGNvbnRlbnQgYXJlYSAqLw0KLnBhZ2UtY29udGVudCB7DQogICAgbWF4LXdpZHRoOiAxNDAlICFpbXBvcnRhbnQ7IA0KICAgIHdpZHRoOiAxNDAlICFpbXBvcnRhbnQ7DQp9DQoNCi8qIEFkanVzdCB0aGUgd2lkdGggb2YgY29kZSBibG9ja3MgKi8NCnByZSwgY29kZSwgcHJlIGNvZGUgew0KICAgIG1heC13aWR0aDogMTAwJSAhaW1wb3J0YW50Ow0KICAgIHdpZHRoOiAxMDAlICFpbXBvcnRhbnQ7DQp9DQoNCi8qIFRoZSB0YWJsZSBvZiBjb250ZW50cyAqLw0KI3RvYyB1bC5uYXYgbGkgdWwgbGkgew0KICAgIGRpc3BsYXk6IG5vbmU7DQogICAgbWF4LWhlaWdodDogbm9uZTsNCn0NCg0KI3RvYyB1bC5uYXYgbGkuYWN0aXZlIHVsIGxpIHsNCiAgICBkaXNwbGF5OiBibG9jazsNCiAgICBtYXgtaGVpZ2h0OiBub25lOw0KfQ0KDQojdG9jIHVsLm5hdiBsaSB1bCBsaSB1bCBsaSB7DQogICAgbWF4LWhlaWdodDogbm9uZTsNCiAgICBkaXNwbGF5OiBub25lICFpbXBvcnRhbnQ7DQp9DQoNCiN0b2MgdWwubmF2IGxpIHVsIGxpLmFjdGl2ZSB1bCBsaSB7DQogICAgbWF4LWhlaWdodDogbm9uZTsNCiAgICBkaXNwbGF5OiBibG9jayAhaW1wb3J0YW50Ow0KfQ0KDQovKiBIZWFkZXIgY29sb3JzICovDQpoMSwgaDIsIGgzLCBoNCwgaDUsIGg2IHsNCiAgICBjb2xvcjogZGVlcHBpbmsgIWltcG9ydGFudDsNCn0NCg0KLyogQWRqdXN0IGZvbnQgc2l6ZXMgaW4gdGhlIFRPQyAqLw0KDQovKiBUb3AtbGV2ZWwgaXRlbXMgKi8NCiN0b2MgdWwubmF2ID4gbGkgPiBhIHsNCiAgICBmb250LXNpemU6IDI1cHggIWltcG9ydGFudDsNCn0NCg0KLyogU2Vjb25kLWxldmVsIGl0ZW1zICovDQojdG9jIHVsLm5hdiBsaSB1bCBsaSA+IGEgew0KICAgIGZvbnQtc2l6ZTogMjBweCAhaW1wb3J0YW50Ow0KfQ0KDQovKiBUaGlyZC1sZXZlbCBpdGVtcyAqLw0KI3RvYyB1bC5uYXYgbGkgdWwgbGkgdWwgbGkgPiBhIHsNCiAgICBmb250LXNpemU6IDE4cHggIWltcG9ydGFudDsNCn0NCg0KPC9zdHlsZT4NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0NCiMga25pdHIgc2V0dGluZw0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBtZXNzYWdlID0gRkFMU0UsDQogIHdhcm5pbmcgPSBGQUxTRSwgDQogIHRpZHkgPSBUUlVFLA0KICBjYWNoZSA9IFRSVUUsDQogIGVjaG89VFJVRQ0KKQ0KYGBgDQoNCiMgKipJbnRyb2R1Y3Rpb24qKiANCg0KVGhpcyBSbWFya2Rvd24gZmlsZSBzdW1tYXJpc2VzIGFsbCBjb2RlIHVzZWQgdG8gcHJvY2VzcywgYW5hbHlzZSwgYW5kIHZpc3VhbGlzZSB0aGUgZGF0YS4NCkhvd2V2ZXIsIG5vdGUgdGhhdCB0aGUgY29kZSBmb3IgYWxsIHN0YXRpc3RpY2FsIG1vZGVscyByZXF1aXJlcyBleHRlbnNpdmUgY29tcHV0YXRpb25hbCBwb3dlciwgYW5kIHJhbiBvbiB0aGUgY29tcHV0YXRpb25hbCBjbHVzdGVyIEthdGFuYSBzdXBwb3J0ZWQgYnkgUmVzZWFyY2ggVGVjaG5vbG9neSBTZXJ2aWNlcyBhdCB0aGUgVW5pdmVyc2l0eSBvZiBOZXcgU291dGggV2FsZXMsIFN5ZG5leSAoaHR0cHM6Ly9yZXNlYXJjaC51bnN3LmVkdS5hdS9rYXRhbmEpLiANClBsZWFzZSBzZWUgdGhlIGZvbGRlciAvUiB0byBmaW5kIHRoZSBmaWxlcyB0aGF0IHdlcmUgdXNlZCB0byBydW4gdGhlIHN0YXRpc3RpY2FsIG1vZGVscyBzZXBhcmF0ZWx5IGFuZCB0aGUgL3BicyBmb2xkZXIgdG8gZmluZCB0aGUgcmVzb3VyY2VzIG5lZWRlZCB0byBydW4gZWFjaCBtb2RlbC4NCklmIHlvdSBoYXZlIGFueSBxdWVzdGlvbnMgb3IgZmluZCBtaXN0YWtlcyBpbiB0aGUgY29kZSBwcmVzZW50ZWQgYmVsb3csIHBsZWFzZSBjb250YWN0IFBhdHJpY2UgUG90dGllciBhdCBwLnBvdHRpZXJAdW5zdy5lZHUuYXUgDQoNCg0KIyAqKkxvYWQgcGFja2FnZXMqKiANCmBgYHtyfQ0KcGFjbWFuOjpwX2xvYWQodGlkeXZlcnNlLA0KICAgICAgICAgICAgICAgcHVycnIsDQogICAgICAgICAgICAgICBhcGUsDQogICAgICAgICAgICAgICByb3RsLA0KICAgICAgICAgICAgICAgYnJtcywNCiAgICAgICAgICAgICAgIG9yY2hhUmQsDQogICAgICAgICAgICAgICBtZXRhZm9yLA0KICAgICAgICAgICAgICAgZW1tZWFucywNCiAgICAgICAgICAgICAgIHRpZHliYXllcywNCiAgICAgICAgICAgICAgIGdnYmVlc3dhcm0sDQogICAgICAgICAgICAgICBrYWJsZUV4dHJhLA0KICAgICAgICAgICAgICAgZ2d0cmVlLA0KICAgICAgICAgICAgICAgZ2d0cmVlRXh0cmEpDQpzZXQuc2VlZCgyMzQpDQpgYGANCg0KIyAqKkRhdGEgd3JhbmdsaW5nKiogDQoNCiMjICoqTG9hZCByYXcgZGF0YSoqIA0KYGBge3J9DQojIExvYWQgcmF3IGV4dHJhY3RlZCBkYXRhDQpyYXdfZGF0YSA8LSByZWFkX2NzdigiZGF0YV9leHRyYWN0aW9uL2FsbF9leHRyYWN0ZWRfZGF0YS5jc3YiKQ0KcmF3X2RhdGEgPC0gYXMuZGF0YS5mcmFtZShyYXdfZGF0YSkNCg0KIyBSZW5hbWUgYm9keSBzaXplIHZhbHVlcw0KcmF3X2RhdGEkdHJhaXRfdHlwZVtyYXdfZGF0YSR0cmFpdF90eXBlPT0iYm9keSBzaXplIl0gPC0gImJvZHlfc2l6ZSINCnJhd19kYXRhIDwtIHJlbmFtZShyYXdfZGF0YSwgYHBlZXJfcmV2aWV3ZWRgID0gJ3BlZXItcmV2aWV3ZWQnKQ0KDQojIENhbGN1bGF0ZSB0aGUgdGVtcGVyYXR1cmUgZGlmZmVyZW5jZSBiZXR3ZWVuIHNlbGVjdGlvbiB0ZW1wZXJhdHVyZXMgKGluIGFic29sdXRlIHZhbHVlcyBiZWNhdXNlIGl0IGlzIG1vZGVsZWQgaW5kZXBlbmRlbnRseSBmb3Igd2FybWVyIGFuZCBjb2xkZXIgbGluZXMpDQpyYXdfZGF0YSA8LSByYXdfZGF0YSAlPiUgbXV0YXRlKHNlbGVjdF90ZW1wX2RpZmYgPSBhYnModHJlYXRtZW50X3RlbXAgLSBjb250cm9sX3RlbXApKQ0KDQojIENhbGN1bGF0ZSB0aGUgdGVtcGVyYXR1cmUgZGlmZmVyZW5jZSBiZXR3ZWVuIGFzc2F5IGFuZCBjb250cm9sIHRlbXBlcmF0dXJlDQpyYXdfZGF0YSA8LSByYXdfZGF0YSAlPiUgbXV0YXRlKGFzc2F5X3RlbXBfZGlmZiA9IGFzc2F5X3RlbXAgLSBjb250cm9sX3RlbXApDQpgYGANCg0KIyMgKipDb252ZXJ0IGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHRvIFNFLCBhbmQgU0UgdG8gU0QqKg0KDQpUbyB1c2UgZWZmZWN0aXZlIHNhbXBsZSBzaXplIHByb3Blcmx5LCB3ZSBuZWVkIHRvIGZpcnN0IGJhY2stY29udmVydCBlc3RpbWF0ZXMgcmVwb3J0ZWQgYXMgU0UgdG8gU0QuIA0KYGBge3J9DQpwcm9jZXNzZWRfZGF0YSA8LSByYXdfZGF0YSAlPiUgbXV0YXRlKGVycm9yX2NvbnRyb2wgPSBpZmVsc2UoZXJyb3JfdHlwZSA9PSAiY2kiLCBlcnJvcl9jb250cm9sLzEuOTYsIGVycm9yX2NvbnRyb2wpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl90cmVhdG1lbnQgPSBpZmVsc2UoZXJyb3JfdHlwZSA9PSAiY2kiLCBlcnJvcl90cmVhdG1lbnQvMS45NiwgZXJyb3JfdHJlYXRtZW50KSkgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShlcnJvcl90eXBlID0gaWZlbHNlKGVycm9yX3R5cGUgPT0gImNpIiwgInNlIiwgZXJyb3JfdHlwZSkpDQoNCnByb2Nlc3NlZF9kYXRhIDwtIHJhd19kYXRhICU+JSBtdXRhdGUoc2RfY29udHJvbCA9IGlmZWxzZShlcnJvcl90eXBlID09ICJzZSIsIGVycm9yX2NvbnRyb2wqc3FydChuX3VzZWRfY29udHJvbCksIGVycm9yX2NvbnRyb2wpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2RfdHJlYXRtZW50ID0gaWZlbHNlKGVycm9yX3R5cGUgPT0gInNlIiwgZXJyb3JfdHJlYXRtZW50KnNxcnQobl91c2VkX3RyZWF0bWVudCksIGVycm9yX3RyZWF0bWVudCkpDQoNCnByb2Nlc3NlZF9kYXRhIDwtIHByb2Nlc3NlZF9kYXRhICU+JSBtdXRhdGUoc2RfY29udHJvbCA9IGlmZWxzZShzZF9jb250cm9sID09IDAsIE5BLCBzZF9jb250cm9sKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2RfdHJlYXRtZW50ID0gaWZlbHNlKHNkX3RyZWF0bWVudCA9PSAwLCBOQSwgc2RfdHJlYXRtZW50KSkgIyBSZXBsYWNlIHZhbHVlcyBvZiAwIGZvciB0aGUgZXJyb3IgYnkgTkEsIGFzIHRoZXNlIHJlc3VsdCBmcm9tIGEgbGFjayBvZiBzYW1wbGluZy4gDQpgYGANCg0KIyMgKipDYWxjdWxhdGUgZWZmZWN0aXZlIHNhbXBsZSBzaXplcyoqIA0KDQpCZWNhdXNlIHRoZSB0cnVlIGxldmVsIG9mIHJlcGxpY2F0aW9uIGluIGV4cGVyaW1lbnRhbCBldm9sdXRpb24gc3R1ZGllcyBpcyB0aGUgbnVtYmVyIG9mIHJlcGxpY2F0ZSBzZWxlY3Rpb24gbGluZXMsIA0Kd2UgY2FsY3VsYXRlZCBlZmZlY3RpdmUgc2FtcGxlIHNpemVzIHRvIGFjY291bnQgZm9yIHBzZXVkby1yZXBsaWNhdGlvbi4NCkVmZmVjdGl2ZSBzYW1wbGUgc2l6ZXMgd2VyZSBjYWxjdWxhdGVkIGZyb20gZm9ybXVsYXMgaW4gUnV0a293c2thIGV0IGFsLiAyMDEzLiBodHRwczovL2RvaS5vcmcvMTAuMTExMS9qZWIuMTIyODIgDQpJQ0Mgd2FzIHRha2VuIGFzIDAuNSwgd2hpY2ggaXMgY29uc2VydmF0aXZlLiBJdCBhc3N1bWVzIHRoYXQgbGlmZSBoaXN0b3J5IHRyYWl0cyBhcmUgcmVwZWF0YWJsZSBiZXR3ZWVuIHNlbGVjdGlvbiBsaW5lcywgc28gdGhlIGVmZmVjdGl2ZSBzYW1wbGUgc2l6ZSBpcyBjbG9zZXIgdG8gdGhlIG51bWJlciBvZiBsaW5lcyB0aGFuIGl0IGlzIHRvIHRoZSB0b3RhbCBudW1iZXIgb2YgaW5kaXZpZHVhbHMgdGVzdGVkLg0KV2hlbiB0aGUgbnVtYmVyIG9mIGFuaW1hbHMgd2FzIG5vdCBhdmFpbGFibGUsIHRoZSBzYW1wbGUgc2l6ZSB3YXMgdGFrZW4gYXMgdGhlIG51bWJlciBvZiByZXBsaWNhdGVzLg0KYGBge3J9DQojIENhbGN1bGF0ZSBlZmZlY3RpdmUgc2FtcGxlIHNpemVzDQpwcm9jZXNzZWRfZGF0YSA8LSBwcm9jZXNzZWRfZGF0YSAlPiUgDQogIG11dGF0ZShlZmZfbl9jb250cm9sPSBpZmVsc2UoaXMubmEobl9hbmltYWxzX2NvbnRyb2wpPT1UUlVFLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuX2NvbnRyb2wsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5fYW5pbWFsc19jb250cm9sIC8gKDEgKyAwLjUqKChuX2FuaW1hbHNfY29udHJvbC9uX2NvbnRyb2wpLTEpKSksDQogICAgICAgICANCiAgICAgICAgIGVmZl9uX3RyZWF0bWVudD0gaWZlbHNlKGlzLm5hKG5fYW5pbWFsc190cmVhdG1lbnQpPT1UUlVFLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuX3RyZWF0bWVudCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbl9hbmltYWxzX3RyZWF0bWVudCAvICgxICsgMC41Kigobl9hbmltYWxzX3RyZWF0bWVudC9uX3RyZWF0bWVudCktMSkpKSkNCmBgYA0KDQoNCiMjICoqQ2FsY3VsYXRlIGVmZmVjdCBzaXplcyoqIA0KDQojIyMgKipDdXN0b20gZnVuY3Rpb25zKiogDQoNCkhlcmUsIHdlIHVzZSBjdXN0b20gZnVuY3Rpb25zIHRvIGNhbGN1bGF0ZSB0aGUgYXZlcmFnZSBjb2VmZmljaWVudCBvZiB2YXJpYXRpb24gYW5kIGltcHV0ZSBtaXNzaW5nIHN0YW5kYXJkIGRldmlhdGlvbnMuIA0KU2VlIE5ha2FnYXdhIGV0IGFsLiAyMDIzIChNZXRob2RzIGluIEVjb2xvZ3kgYW5kIEV2b2x1dGlvbikNCmBgYHtyfQ0KY3ZfYXZnIDwtIGZ1bmN0aW9uKHgsIHNkLCBuLCBncm91cCwgZGF0YSwgbGFiZWwgPSBOVUxMLCBzdWJfYiA9IFRSVUUsIGN2Mj1GQUxTRSl7DQoNCiAgIyBDaGVjayBpZiB0aGUgbmFtZSBpcyBzcGVjaWZpZWQgb3Igbm90LiBJZiBub3QsIHRoZW4gYXNzaWduIGl0IHRoZSBuYW1lIG9mIHRoZSBtZWFuLCB4LCB2YXJpYWJsZSBpbnB1dCBpbiB0aGUgZnVuY3Rpb24uIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzYwNjQ0NDQ1L2NvbnZlcnRpbmctdGlkeWV2YWwtYXJndW1lbnRzLXRvLXN0cmluZw0KICBpZihpcy5udWxsKGxhYmVsKSl7DQogICAgbGFiZWwgPC0gcHVycnI6Om1hcF9jaHIoZW5xdW9zKHgpLCBybGFuZzo6YXNfbGFiZWwpDQogIH0NCg0KICAjIENhbGN1bGF0ZSBiZXR3ZWVuIHN0dWR5IENWLiBUYWtlIHdlaWdodGVkIG1lYW4gQ1Ygd2l0aGluIHN0dWR5LCBhbmQgdGhlbiB0YWtlIGEgd2VpZ2h0ZWQgbWVhbiBhY3Jvc3Mgc3R1ZGllcyBvZiB0aGUgd2l0aGluIHN0dWR5IENWLiBXZWlnaHRlZCBiYXNlZCBvbiBzYW1wbGUgc2l6ZSBhbmQgcG9vbGVkIHNhbXBsZSBzaXplLg0KICBiX2dycF9jdl9kYXRhIDwtIGRhdGEgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAlPiUNCiAgICBkcGx5cjo6Z3JvdXBfYnkoe3tncm91cH19KSAgICAgICAgICAgICAgICAgICAgICAgICAgICAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKCAgIHdfQ1YyID0gd2VpZ2h0ZWRfQ1Yoe3tzZH19LCB7e3h9fSwge3tufX0sIGN2Mj1jdjIpLA0KICAgICAgICAgICAgICAgICAgICAgbl9tZWFuID0gbWVhbih7e259fSwgbmEucm0gPSBUUlVFKSkgICAlPiUNCiAgICBkcGx5cjo6dW5ncm91cCguKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKGJfQ1YyID0gd2VpZ2h0ZWQubWVhbih3X0NWMiwgbl9tZWFuLCBuYS5ybSA9IFRSVUUpLCAua2VlcCA9ICJ1c2VkIikNCg0KICAjIE1ha2Ugc3VyZSB0aGF0IGxhYmVsIG9mIHRoZSBjYWxjdWxhdGVkIGNvbHVtbnMgaXMgZGlzdGluY3QgZnJvbSBhbnkgb3RoZXIgY29sdW1ucw0KICBuYW1lcyhiX2dycF9jdl9kYXRhKSA8LSBwYXN0ZTAobmFtZXMoYl9ncnBfY3ZfZGF0YSksICJfIiwgbGFiZWwpDQoNCiAgIyBBcHBlbmQgdGhlc2UgY2FsY3VsYXRlZCBjb2x1bW5zIGJhY2sgdG8gdGhlIG9yaWdpbmFsIGRhdGEgYW5kIHJldHVybiB0aGUgZnVsbCBkYXRhc2V0Lg0KICBpZihzdWJfYil7DQogICAgYl9ncnBfY3ZfZGF0YSA8LSBiX2dycF9jdl9kYXRhICU+JSBkcGx5cjo6c2VsZWN0KGdyZXAoImJfIiwgbmFtZXMoYl9ncnBfY3ZfZGF0YSkpKQ0KICAgIGRhdF9uZXcgPC0gY2JpbmQoZGF0YSwgYl9ncnBfY3ZfZGF0YSkNCiAgfSBlbHNlIHsNCiAgICBkYXRfbmV3IDwtIGNiaW5kKGRhdGEsIGJfZ3JwX2N2X2RhdGEpDQogIH0NCg0KICByZXR1cm4oZGF0YS5mcmFtZShkYXRfbmV3KSkNCn0NCg0KIyBIZWxwZXIgZnVuY3Rpb24NCndlaWdodGVkX0NWIDwtIGZ1bmN0aW9uKHNkLCB4LCBuLCBjdjI9RkFMU0Upew0KICBpZihjdjIpew0KICAgIHdlaWdodGVkLm1lYW4obmFfaWYoKHNkIC8geCleMiwgSW5mKSwgbiwgbmEucm0gPSBUUlVFKQ0KICB9ZWxzZXsNCiAgICB3ZWlnaHRlZC5tZWFuKG5hX2lmKChzZCAvIHgpLCBJbmYpLCBuLCBuYS5ybSA9IFRSVUUpXjINCiAgfQ0KfQ0KYGBgDQoNCg0KIyMjICoqSW1wdXRlIG1pc3Npbmcgc3RhbmRhcmQgZGV2aWF0aW9ucyBhbmQgY2FsY3VsYXRlIGVmZmVjdCBzaXplcyoqDQoNCkRpZmZlcmVudCBmb3JtdWxhcyB3ZXJlIHVzZWQgZm9yIGluZGVwZW5kZW50IGFuZCBkZXBlbmRlbnQgc2FtcGxlcyAoc2VlIG1ldGhvZHMpLg0KYGBge3J9DQojIENhbGN1bGF0ZSBhdmVyYWdlIHN0YW5kYXJkIGRldmlhdGlvbnMNCnByb2Nlc3NlZF9kYXRhIDwtIGN2X2F2Zyh4PW1lYW5fY29udHJvbCwgc2QgPSBzZF9jb250cm9sLCBuPWVmZl9uX2NvbnRyb2wsIGdyb3VwID0gcmVmLCBsYWJlbCA9ICJjb250cm9sIiwgZGF0YSA9IHByb2Nlc3NlZF9kYXRhKSAjIENvbnRyb2wNCnByb2Nlc3NlZF9kYXRhIDwtIGN2X2F2Zyh4PW1lYW5fdHJlYXRtZW50LCBzZCA9IHNkX3RyZWF0bWVudCwgbj1lZmZfbl90cmVhdG1lbnQsIGdyb3VwID0gcmVmLCBsYWJlbCA9ICJ0cmVhdG1lbnQiLCBkYXRhID0gcHJvY2Vzc2VkX2RhdGEpICMgVHJlYXRtZW50DQoNCiMgTXVsdGlwbHkgdGhlIGNvZWZmaWNpZW50IG9mIHZhcmlhdGlvbiBieSB0aGUgbWVhbiB0byBnZXQgU0QNCnByb2Nlc3NlZF9kYXRhIDwtIHByb2Nlc3NlZF9kYXRhICU+JSBtdXRhdGUoc2RfY29udHJvbCA9IGlmZWxzZShpcy5uYShzZF9jb250cm9sKT09VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiX0NWMl9jb250cm9sKm1lYW5fY29udHJvbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZF9jb250cm9sKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2RfdHJlYXRtZW50ID0gaWZlbHNlKGlzLm5hKHNkX3RyZWF0bWVudCk9PVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYl9DVjJfdHJlYXRtZW50Km1lYW5fdHJlYXRtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkX3RyZWF0bWVudCkpDQoNCiMgQWRkIGEgY29sdW1uIHRvIGlkZW50aWZ5IG9ic2VydmF0aW9ucyBzaGFyaW5nIHRoZSBzYW1lIGNvaG9ydCBJRHMNCnByb2Nlc3NlZF9kYXRhIDwtIHByb2Nlc3NlZF9kYXRhICU+JQ0KICBncm91cF9ieShjb2hvcnRfSUQpICU+JQ0KICBtdXRhdGUobl9jb2hvcnQgPSBuKCkpICU+JQ0KICB1bmdyb3VwKCkNCg0KIyBDYWxjdWxhdGUgZWZmZWN0IHNpemVzIGZvciBpbmRlcGVuZGVudCBhbmQgZGVwZW5kZW50ICh0cmFpdHMgbWVhc3VyZWQgb24gdGhlIHNhbWUgYW5pbWFscykgc2FtcGxlcy4NCnByb2Nlc3NlZF9kYXRhIDwtIHByb2Nlc3NlZF9kYXRhICU+JSBtdXRhdGUoDQogICMgTG9nIHJlc3BvbnNlIHJhdGlvIChsblJSKQ0KICBsblJSID0gbG9nKG1lYW5fdHJlYXRtZW50L21lYW5fY29udHJvbCkgKyANCiAgICAgICAgICAgICAgICAoMC41ICogKChzZF90cmVhdG1lbnReMi8oZWZmX25fdHJlYXRtZW50Km1lYW5fdHJlYXRtZW50XjIpKSAtICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAoc2RfY29udHJvbF4yLyhlZmZfbl9jb250cm9sKm1lYW5fY29udHJvbF4yKSkpKSwgIyBGb3JtdWxhIDQgaW4gU2VuaW9yIGV0IGFsLiAyMDIwDQogICAgDQogICMgU2FtcGxpbmcgdmFyaWFuY2Ugb2YgbG5SUg0KICB2YXJfbG5SUiA9IGlmZWxzZShuX2NvaG9ydCA9PSAxLCAjIElmIHNhbXBsZXMgYXJlIGluZGVwZW5kZW50DQogICAgDQogICAgICAgICAgICAgKHNkX2NvbnRyb2xeMi8oZWZmX25fY29udHJvbCptZWFuX2NvbnRyb2xeMikpICsgDQogICAgICAgICAgICAgKHNkX2NvbnRyb2xeNC8oMiplZmZfbl9jb250cm9sXjIqbWVhbl9jb250cm9sXjQpKSArIA0KICAgICAgICAgICAgIChzZF90cmVhdG1lbnReMi8oZWZmX25fdHJlYXRtZW50Km1lYW5fdHJlYXRtZW50XjIpKSArDQogICAgICAgICAgICAgKHNkX3RyZWF0bWVudF40LygyKmVmZl9uX3RyZWF0bWVudF4yKm1lYW5fdHJlYXRtZW50XjQpKSwgIyBGb3JtdWxhIDE0IGluIFNlbmlvciBldCBhbC4gMjAyMA0KICANCiAgICAgICAgICAgICAoc2RfY29udHJvbF4yLyhlZmZfbl9jb250cm9sKm1lYW5fY29udHJvbF4yKSkgKyAgIyBlbHNlIHVzZSB0aGlzIGZvcm11bGEgaWYgc2FtcGxlcyBhcmUgZGVwZW5kZW50DQogICAgICAgICAgICAgKHNkX3RyZWF0bWVudF4yLyhlZmZfbl90cmVhdG1lbnQqbWVhbl90cmVhdG1lbnReMikpICsNCiAgICAgICAgICAgICAoc2RfY29udHJvbF40LygyKmVmZl9uX2NvbnRyb2xeMiptZWFuX2NvbnRyb2xeNCkpICsgDQogICAgICAgICAgICAgKHNkX3RyZWF0bWVudF40LygyKmVmZl9uX3RyZWF0bWVudF4yKm1lYW5fdHJlYXRtZW50XjQpKSAtIA0KICAgICAgICAgICAgICgwLjUgKiAoKDIqc2RfY29udHJvbCpzZF90cmVhdG1lbnQpLyhlZmZfbl9jb250cm9sKm1lYW5fY29udHJvbCptZWFuX3RyZWF0bWVudCkpKSArIA0KICAgICAgICAgICAgICgwLjVeMiAqICgoc2RfY29udHJvbF4yKnNkX3RyZWF0bWVudF4yKihtZWFuX2NvbnRyb2xeNCttZWFuX3RyZWF0bWVudF40KSkvKDIqZWZmX25fY29udHJvbF4yKm1lYW5fY29udHJvbF40Km1lYW5fdHJlYXRtZW50XjQpKSkgIyBGb3JtdWxhIDE5IGluIFNlbmlvciBldCBhbC4gMjAyMA0KICApLA0KICANCiAgIyBMb2cgdmFyaWFuY2UgcmF0aW8gKGxuVlIpDQogIGxuVlIgPSBsb2coc2RfdHJlYXRtZW50L3NkX2NvbnRyb2wpICsgDQogICAgICAgICAgICAgICAgKDAuNSAqICgoMS8oZWZmX25fdHJlYXRtZW50LTEpKSAtICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAoMS8oZWZmX25fY29udHJvbC0xKSkpKSwgIyBGb3JtdWxhIDUgaW4gU2VuaW9yIGV0IGFsLiAyMDIwDQogIA0KICAjIFNhbXBsaW5nIHZhcmlhbmNlIG9mIGxuVlINCiAgdmFyX2xuVlIgPSBpZmVsc2Uobl9jb2hvcnQgPT0xLCAjIElmIHNhbXBsZXMgYXJlIGluZGVwZW5kZW50DQogICAgDQogICAgMC41ICogKChlZmZfbl9jb250cm9sLygoZWZmX25fY29udHJvbC0xKV4yKSkgKyAoZWZmX25fdHJlYXRtZW50LygoZWZmX25fdHJlYXRtZW50LTEpXjIpKSksICMgRm9ybXVsYSAxNSBpbiBTZW5pb3IgZXQgYWwuIDIwMjANCiAgICAoZWZmX25fY29udHJvbC8oZWZmX25fY29udHJvbCAtIDEpXjIpIC0gKDAuNV4yKigxLyhlZmZfbl9jb250cm9sLTEpKSkgKyAoMC41XjQqKChzZF9jb250cm9sXjgrc2RfdHJlYXRtZW50XjgpLygyKigoZWZmX25fY29udHJvbC0xKV4yKSpzZF9jb250cm9sXjQqc2RfdHJlYXRtZW50XjQpKSkgIyBGb3JtdWxhIDIyIGluIFNlbmlvciBldCBhbC4gMjAyMA0KICApLCAgICAgICANCiAgDQogICMgTG9nIGNvZWZmaWNpZW50IG9mIHZhcmlhdGlvbiByYXRpbyAobG5DVlIpDQogIGxuQ1ZSID0gbG9nKChzZF90cmVhdG1lbnQvbWVhbl90cmVhdG1lbnQpLyhzZF9jb250cm9sL21lYW5fY29udHJvbCkpICsgDQogICAgICAgICAgICAgICAgKDAuNSAqICgoMS8oZWZmX25fdHJlYXRtZW50LTEpKSAtICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAoMS8oZWZmX25fY29udHJvbC0xKSkpKSArIA0KICAgICAgICAgICAgICAgICgwLjUgKiAoKHNkX2NvbnRyb2xeMi8oZWZmX25fY29udHJvbCptZWFuX2NvbnRyb2xeMikpIC0gICAgDQogICAgICAgICAgICAgICAgICAgICAgIChzZF90cmVhdG1lbnReMi8oZWZmX25fdHJlYXRtZW50Km1lYW5fdHJlYXRtZW50XjIpKSkpLCAjIEZvcm11bGEgNiBpbiBTZW5pb3IgZXQgYWwuIDIwMjANCiAgDQogICMgU2FtcGxpbmcgdmFyaWFuY2Ugb2YgbG5DVlINCiAgdmFyX2xuQ1ZSID0gaWZlbHNlKG5fY29ob3J0PT0xLCAjIElmIHNhbXBsZXMgYXJlIGluZGVwZW5kZW50DQogICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAoc2RfY29udHJvbF4yLyhlZmZfbl9jb250cm9sKm1lYW5fY29udHJvbF4yKSkgKyANCiAgICAgICAgICAgICAgKHNkX2NvbnRyb2xeNC8oMiplZmZfbl9jb250cm9sXjIqbWVhbl9jb250cm9sXjQpKSArIA0KICAgICAgICAgICAgICAoZWZmX25fY29udHJvbC8oKGVmZl9uX2NvbnRyb2wtMSleMikpICsgDQogICAgICAgICAgICAgIChzZF90cmVhdG1lbnReMi8oZWZmX25fdHJlYXRtZW50Km1lYW5fdHJlYXRtZW50XjIpKSArIA0KICAgICAgICAgICAgICAoc2RfdHJlYXRtZW50XjQvKDIqZWZmX25fdHJlYXRtZW50XjIqbWVhbl90cmVhdG1lbnReNCkpICsgDQogICAgICAgICAgICAgIChlZmZfbl90cmVhdG1lbnQvKChlZmZfbl90cmVhdG1lbnQtMSleMikpLCAjIEZvcm11bGEgMTYgaW4gU2VuaW9yIGV0IGFsLiAyMDIwDQogICANCiAgICAgICAgICAgICAgKHNkX2NvbnRyb2xeMi8oZWZmX25fY29udHJvbCptZWFuX2NvbnRyb2xeMikpICsgDQogICAgICAgICAgICAgIChzZF90cmVhdG1lbnReMi8oZWZmX25fdHJlYXRtZW50Km1lYW5fdHJlYXRtZW50XjIpKSArIA0KICAgICAgICAgICAgICAoc2RfY29udHJvbF40LygyKmVmZl9uX2NvbnRyb2xeMiptZWFuX2NvbnRyb2xeNCkpICsgDQogICAgICAgICAgICAgIChzZF90cmVhdG1lbnReNC8oMiplZmZfbl90cmVhdG1lbnReMiptZWFuX3RyZWF0bWVudF40KSkgLSANCiAgICAgICAgICAgICAgKDAuNSAqICgoMipzZF9jb250cm9sKnNkX3RyZWF0bWVudCkvKGVmZl9uX2NvbnRyb2wqbWVhbl9jb250cm9sKm1lYW5fdHJlYXRtZW50KSkpICsgDQogICAgICAgICAgICAgICgwLjVeMiAqIChzZF9jb250cm9sXjIqc2RfdHJlYXRtZW50XjIqKG1lYW5fY29udHJvbF40K21lYW5fdHJlYXRtZW50XjQpKS8oMiplZmZfbl9jb250cm9sXjIqbWVhbl9jb250cm9sXjQqbWVhbl90cmVhdG1lbnReNCkpICsgDQogICAgICAgICAgICAgIChlZmZfbl9jb250cm9sLygoZWZmX25fY29udHJvbC0xKV4yKSkgLSANCiAgICAgICAgICAgICAgKDAuNV4yICogKDEvKGVmZl9uX2NvbnRyb2wtMSkpKSArIA0KICAgICAgICAgICAgICAoMC41XjQgKiAoc2RfY29udHJvbF44K3NkX3RyZWF0bWVudF44KS8oMiooKGVmZl9uX2NvbnRyb2wtMSleMikqc2RfY29udHJvbF40KnNkX3RyZWF0bWVudF40KSkgIyBGb3JtdWxhIDI0IGluIFNlbmlvciBldCBhbC4gMjAyMA0KICApKQ0KYGBgDQoNCg0KIyMgKipTYXZlIHByb2Nlc3NlZCBkYXRhc2V0KioNCmBgYHtyLCBldmFsID0gRn0NCiMgU2F2ZSBwcm9jZXNzZWQgZGF0YSANCndyaXRlLmNzdihwcm9jZXNzZWRfZGF0YSwgZmlsZSA9ICJkYXRhL3Byb2Nlc3NlZF9kYXRhLmNzdiIpDQpgYGANCg0KIyMgKipBY2NvdW50IGZvciBkYXRhIG5vbi1pbmRlcGVuZGVuY2UqKg0KDQojIyMgKipQaHlsb2dlbmV0aWMgdmFyaWF0aW9uKiogDQpgYGB7ciwgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQgPSAxNX0NCnByb2Nlc3NlZF9kYXRhIDwtIHJlYWRfY3N2KGZpbGUgPSAiZGF0YS9wcm9jZXNzZWRfZGF0YS5jc3YiKQ0KDQpkYXRhIDwtIHByb2Nlc3NlZF9kYXRhDQp1bmlxdWUoZGF0YSRzcGVjaWVzKSAjIDI1IHNwZWNpZXMNCg0KIyBNYXRjaCBzcGVjaWVzIHRvIHRoZSBPVEwgZGF0YWJhc2UNCnRheGEgPC0gdW5pcXVlKGRhdGEkc3BlY2llcykNCnJlc29sdmVkX25hbWVzIDwtIHRucnNfbWF0Y2hfbmFtZXModGF4YSwgY29udGV4dF9uYW1lID0gIkFuaW1hbHMiKQ0KcmVzb2x2ZWRfbmFtZXMgIyBBbGwgZ29vZCwgbm8gYXBwcm94aW1hdGUgbWF0Y2hlcw0KDQojIENyZWF0ZSB0cmVlDQp0cmVlIDwtIHRvbF9pbmR1Y2VkX3N1YnRyZWUob3R0X2lkcyA9IHJlc29sdmVkX25hbWVzJG90dF9pZCkNCnRyZWUkdGlwLmxhYmVsIDwtIHN0cmlwX290dF9pZHModHJlZSR0aXAubGFiZWwpICMgUmVtb3ZlIG90dCBJRHMgZm9yIHByZXNlbnRhdGlvbg0KI3Bsb3QodHJlZSwgbm8ubWFyZ2luPVRSVUUsIGNleD0xKQ0KDQp0cmVlIDwtIG11bHRpMmRpKHRyZWUsIHJhbmRvbSA9IFRSVUUpICMgUmVzb2x2ZSBwb2x5dG9teSBhdCByYW5kb20sIGJ1dCBpdCBtYXRjaGVzIGNsYXNzaWZpY2F0aW9uIGZyb20gQ29ybmV0dGkgZXQgYWwuIDIwMTkuIE1vbGVjdWxhciBQaHlsb2dlbmV0aWNzIGFuZCBFdm9sdXRpb247IHdpdGggRC4gcHVsZXggYW5kIEQuIHB1bGljYXJpYSBiZWluZyBtb3JlIGNsb3NlbHkgcmVsYXRlZCB0byBlYWNob3RoZXIgdGhhbiBELiBtYWduYQ0KcGh5bG9fdHJlZSA8LSBjb21wdXRlLmJybGVuKHRyZWUsIG1ldGhvZCA9ICJHcmFmZW4iLCBwb3dlciA9IDEpICMgQ29tcHV0ZSBicmFuY2ggbGVuZ3Rocw0KDQojIFBsb3QgdHJlZQ0KcGxvdChwaHlsb190cmVlKQ0KDQojIENvbXB1dGUgcGh5bG9nZW5ldGljIGNvcnJlbGF0aW9uIG1hdHJpeA0KcGh5bG9fbWF0cml4IDwtIHZjdihwaHlsb190cmVlLCBjb3IgPSBUKSAgIyBUaGUgdmN2IGZ1bmN0aW9uIHJldHVybnMgYSB2YXJpYW5jZS1jb3ZhcmlhbmNlIG1hdHJpeA0KDQojIEFkZCBhbiBhZGRpdGlvbmFsIGNvbHVtbiBmb3IgcGh5bG9nZW55DQpkYXRhIDwtIG11dGF0ZShkYXRhLCBwaHlsb2dlbnkgPSBnc3ViKCIgIiwgIl8iLCBzcGVjaWVzKSwNCiAgICAgICAgICAgICAgIG9icyA9IHJvd19udW1iZXIoKSkNCg0KIyBDb252ZXJ0IHRpYmJsZSB0byBkYXRhIGZyYW1lDQpkYXRhIDwtIGFzLmRhdGEuZnJhbWUoZGF0YSkNCg0KIyBSZW5hbWUgdHJhaXQgdHlwZQ0KZGF0YSR0cmFpdF90eXBlIDwtIGZhY3RvcihkYXRhJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCiMgUmVuYW1lIHRlbXBlcmF0dXJlIHJlZ2ltZQ0KZGF0YSR3YXJtX2NvbGQgPC0gZmFjdG9yKGRhdGEkd2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiY29sZCIsICJ3YXJtIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJDb2xkIiwgIldhcm0iKSkNCmBgYA0KDQojIyMgKipOb24taW5kZXBlbmRlbmNlIGR1ZSB0byBzaGFyZWQgY29ob3J0cyoqIA0KDQpCZWNhdXNlIGRpZmZlcmVudCB0cmFpdHMgd2VyZSBzb21ldGltZXMgbWVhc3VyZWQgb24gdGhlIGNvaG9ydCBvZiBhbmltYWxzLCB3ZSBhY2NvdW50IGZvciB0aGlzIHNvdXJjZSBvZiBub24taW5kZXBlbmRlbmNlIHdpdGggYSB2YXJpYW5jZS1jb3ZhcmlhbmNlIG1hdHJpeCB0byBjb3JyZWxhdGUgZXJyb3JzIG9mIGVhY2ggdHJhaXQgKGNmLiBOb2JsZSBldCBhbC4gMjAxNykNCmBgYHtyfQ0KIyBWQ1YgbWF0cml4IGZvciBsblJSIA0KVkNWX2xuUlIgPC0gdmNhbGModmkgPSB2YXJfbG5SUiwNCiAgICAgICAgICAgICAgICAgIGNsdXN0ZXIgPSBzaGFyZWRfY29udHJvbF9JRCwgDQogICAgICAgICAgICAgICAgICByaG8gPSAwLjUsDQogICAgICAgICAgICAgICAgICBvYnMgPSBvYnMsDQogICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSkgDQoNCiMgVkNWIG1hdHJpeCBmb3IgbG5DVlINClZDVl9sbkNWUiA8LSB2Y2FsYyh2aSA9IHZhcl9sbkNWUiwNCiAgICAgICAgICAgICAgICAgIGNsdXN0ZXIgPSBzaGFyZWRfY29udHJvbF9JRCwgDQogICAgICAgICAgICAgICAgICByaG8gPSAwLjUsDQogICAgICAgICAgICAgICAgICBvYnMgPSBvYnMsDQogICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSkgDQoNCiMgVkNWIG1hdHJpeCBmb3IgbG5WUg0KVkNWX2xuVlIgPC0gdmNhbGModmkgPSB2YXJfbG5WUiwNCiAgICAgICAgICAgICAgICAgIGNsdXN0ZXIgPSBzaGFyZWRfY29udHJvbF9JRCwgDQogICAgICAgICAgICAgICAgICByaG8gPSAwLjUsDQogICAgICAgICAgICAgICAgICBvYnMgPSBvYnMsDQogICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSkgDQpgYGANCg0KDQojICoqT3ZlcnZpZXcgb2YgdGhlIGRhdGFzZXQqKiANCg0KYGBge3J9DQojIFN1bW1hcml6ZSBvdmVyYWxsIG1ldHJpY3MNCm92ZXJhbGwgPC0gZGF0YSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIEdyb3VwID0gIk92ZXJhbGwiLA0KICAgIGBOdW1iZXIgb2YgU3R1ZGllc2AgPSBuX2Rpc3RpbmN0KHJlZiksDQogICAgYE51bWJlciBvZiBTcGVjaWVzYCA9IG5fZGlzdGluY3Qoc3BlY2llcyksDQogICAgYE51bWJlciBvZiBFZmZlY3QgU2l6ZXNgID0gbl9kaXN0aW5jdChvYnMpDQogICkNCg0KIyBTdW1tYXJpemUgYnkgdHJhaXQNCmJ5X3RyYWl0IDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgR3JvdXAgPSBwYXN0ZSgiVHJhaXQgLSIsIHVuaXF1ZSh0cmFpdF90eXBlKSksDQogICAgYE51bWJlciBvZiBTdHVkaWVzYCA9IG5fZGlzdGluY3QocmVmKSwNCiAgICBgTnVtYmVyIG9mIFNwZWNpZXNgID0gbl9kaXN0aW5jdChzcGVjaWVzKSwNCiAgICBgTnVtYmVyIG9mIEVmZmVjdCBTaXplc2AgPSBuX2Rpc3RpbmN0KG9icykNCiAgKSAlPiUNCiAgdW5ncm91cCgpDQoNCiMgU3VtbWFyaXplIGJ5IHRlbXBlcmF0dXJlIHJlZ2ltZQ0KYnlfdGVtcGVyYXR1cmUgPC0gZGF0YSAlPiUNCiAgZ3JvdXBfYnkod2FybV9jb2xkKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIEdyb3VwID0gcGFzdGUoIlRlbXBlcmF0dXJlIHJlZ2ltZSAtIiwgdW5pcXVlKHdhcm1fY29sZCkpLA0KICAgIGBOdW1iZXIgb2YgU3R1ZGllc2AgPSBuX2Rpc3RpbmN0KHJlZiksDQogICAgYE51bWJlciBvZiBTcGVjaWVzYCA9IG5fZGlzdGluY3Qoc3BlY2llcyksDQogICAgYE51bWJlciBvZiBFZmZlY3QgU2l6ZXNgID0gbl9kaXN0aW5jdChvYnMpDQogICkgJT4lDQogIHVuZ3JvdXAoKQ0KDQojIENvbWJpbmUgYWxsIHN1bW1hcmllcw0KdGFibGVfc2FtcGxlX3NpemVzIDwtIGJpbmRfcm93cyhvdmVyYWxsLCBieV90cmFpdCwgYnlfdGVtcGVyYXR1cmUpICU+JSANCiAgZHBseXI6OnNlbGVjdCgtdHJhaXRfdHlwZSwgLXdhcm1fY29sZCkNCg0KIyBDcmVhdGUgdGhlIHRhYmxlDQp0YWJsZV9zYW1wbGVfc2l6ZXMgJT4lDQogIGthYmxlKCkgJT4lDQogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBwb3NpdGlvbiA9ICJjZW50ZXIiLCBmaXhlZF90aGVhZCA9IFRSVUUpICU+JQ0KICBjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSwgYm9yZGVyX3JpZ2h0ID0gVFJVRSkgJT4lDQogIHJvd19zcGVjKDAsIGJhY2tncm91bmQgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIsIGJvbGQgPSBUUlVFKSAlPiUNCiAga2FibGVfc3R5bGluZyhmaXhlZF90aGVhZCA9IFRSVUUpDQogICAgDQpgYGANCg0KDQojICoqTWFpbiBtZXRhLWFuYWx5dGljIG1vZGVscyoqIA0KDQpOb3RlIHRoYXQgdGhlc2UgbW9kZWxzIHRha2UgYSBzdWJzdGFudGlhbCBhbW91bnQgb2YgdGltZSB0byBydW4uIFRoZXJlZm9yZSwgdGhlc2UgbW9kZWxzIHdlcmUgcmFuIG9uIHRoZSBjb21wdXRhdGlvbmFsIGNsdXN0ZXIgS2F0YW5hLCBzdXBwb3J0ZWQgYnkgUmVzZWFyY2ggVGVjaG5vbG9neSBTZXJ2aWNlcyBhdCBVTlNXIFN5ZG5leS4gDQpSZXNvdXJjZXMgbmVlZGVkIHRvIHJ1biB0aGVzZSBtb2RlbHMgYXJlIHByb3ZpZGVkIGluIHRoZSAvcGJzLyBmb2xkZXIsIGFuZCB0aGUgUiBjb2RlIHVzZWQgZm9yIGVhY2ggbW9kZWwgaXMgaW4gdGhlIFIvbW9kZWxzLyBmb2xkZXIuIA0KDQojIyAqKkNoYW5nZXMgaW4gdHJhaXQgbWVhbnMgKGxuUlIpKiogIHsudGFic2V0IC50YWJzZXRfZmFkZSAudGFic2V0X3BpbGxzfQ0KDQojIyMgKipPdmVyYWxsIG1vZGVsKioNCg0KIyMjIyAqTW9kZWwgc3BlY2lmaWNhdGlvbioNCmBgYHtyLCBldmFsID0gRn0NCiMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KZm9ybXVsYSA8LSBiZihsblJSIH4gdHJhaXRfdHlwZSAtMSArICMgU2VwYXJhdGUgZWZmZWN0cyBieSB0cmFpdCB0eXBlDQogICAgICAgICAgICAgICAgKHRyYWl0X3R5cGUtMXxyZWYpICsgIyBDb3JyZWxhdGlvbiBiZXR3ZWVuIHRyYWl0cyBhbW9uZyBzdHVkaWVzDQogICAgICAgICAgICAgICAgKDF8c3BlY2llcykgKyAjIFNwZWNpZXMtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfGdyKHBoeWxvZ2VueSwgY292ID0gcGh5bG9fbWF0cml4KSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5SUikpICMgVmFyaWFuY2UgY292YXJpYW5jZSBtYXRpeCBvZiBjb3JyZWxhdGVkIHNhbXBsaW5nIHZhcmlhbmNlcw0KDQojIERlZmluZSBwcmlvcnMNCnByaW9yID0gYygNCiAgcHJpb3IoY29uc3RhbnQoMSksIGNsYXNzID0gInNpZ21hIikNCikgIyBCZWNhdXNlIHRoZSByZXNpZHVhbCB2YXJpYW5jZS1jb3ZhcmlhbmNlIHN0cnVjdHVyZSBpcyBzcGVjaWZpZWQgaW4gZmNvciwgdGhlcmUgaXMgbm8gbmVlZCB0byBlc3RpbWF0ZSBzaWdtYSBzbyBpdCBpcyBsZWZ0IGFzIGEgY29uc3RhbnQNCg0KIyBGaXQgbW9kZWwNCmxuUlJfbW9kZWxfb3ZlcmFsbCA8LSBicm0oZm9ybXVsYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBnYXVzc2lhbigpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTIgPSBsaXN0KHBoeWxvX21hdHJpeCA9IHBoeWxvX21hdHJpeCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWQ1ZfbG5SUiA9IFZDVl9sblJSKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yID0gcHJpb3IsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyID0gNDAwMCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICB3YXJtdXAgPSAyMDAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhaW5zID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JlcyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEyMykgDQoNCiMgU2F2ZSBtb2RlbA0Kc2F2ZVJEUyhsblJSX21vZGVsX292ZXJhbGwsIGZpbGUgPSAiUkRhdGEvbG5SUl9tb2RlbF9vdmVyYWxsLnJkcyIpDQpgYGANCg0KIyMjIyAqTW9kZWwgb3V0cHV0Kg0KYGBge3J9DQojIExvYWQgbW9kZWwNCmxuUlJfbW9kZWxfb3ZlcmFsbCA8LSByZWFkUkRTKCJSRGF0YS9sblJSX21vZGVsX292ZXJhbGwucmRzIikNCg0KIyBEaXNwbGF5IG1vZGVsIG91dHB1dCANCnN1bW1hcnkobG5SUl9tb2RlbF9vdmVyYWxsKQ0KDQojIENsZWFuZWQgbW9kZWwgb3V0cHV0DQphcy5kYXRhLmZyYW1lKGZpeGVmKGxuUlJfbW9kZWxfb3ZlcmFsbCwgc3VtbWFyeSA9IFRSVUUpKSAlPiUNCiAgIyBSZW5hbWUgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGZvciBjbGVhbmVyIGRpc3BsYXkNCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJQYXJhbWV0ZXIiKSAlPiUgDQogIG11dGF0ZSgNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspIiwgIlxcMSIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkhldGVyb2dlbmVpdHkgYW5hbHlzaXMqDQpgYGB7cn0NCiMgRXh0cmFjdGluZyB0aGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbiBmcm9tIHRoZSBtb2RlbA0KcG9zdGVyaW9yIDwtIHBvc3Rlcmlvcl9zYW1wbGVzKGxuUlJfbW9kZWxfb3ZlcmFsbCkNCg0KIyBDYWxjdWxhdGUgbWVhc3VyZW1lbnQgZXJyb3IgdmFyaWFuY2UNCnNpZ21hMl92IDwtIHN1bSgxL2RpYWcoVkNWX2xuUlIpKSAqIChsZW5ndGgoZGlhZyhWQ1ZfbG5SUikpLSAxKS8oc3VtKDEvZGlhZyhWQ1ZfbG5SUikpXjIgLSBzdW0oKDEvZGlhZyhWQ1ZfbG5SUikpXjIpKQ0KDQojIENhbGN1bGF0ZSB0aGUgdG90YWwgdmFyaWFuY2UgKGluY2x1ZGluZyB0aGUgbWVhc3VyZW1lbnQgZXJyb3IgdmFyaWFuY2UpDQp2YXJfdG90YWwgPC0gcG9zdGVyaW9yJHNkX2V4cGVyaW1lbnRfSURfX0ludGVyY2VwdCArDQogICAgICAgICAgICAgcG9zdGVyaW9yJHNkX29ic19fSW50ZXJjZXB0ICsNCiAgICAgICAgICAgICBwb3N0ZXJpb3Ikc2RfcGh5bG9nZW55X19JbnRlcmNlcHQgKw0KICAgICAgICAgICAgIHBvc3RlcmlvciRzZF9yZWZfX3RyYWl0X3R5cGVib2R5X3NpemUgKw0KICAgICAgICAgICAgIHBvc3RlcmlvciRzZF9yZWZfX3RyYWl0X3R5cGVmZWN1bmRpdHkgKw0KICAgICAgICAgICAgIHBvc3RlcmlvciRzZF9yZWZfX3RyYWl0X3R5cGVzdXJ2aXZhbCArDQogICAgICAgICAgICAgcG9zdGVyaW9yJHNkX3NwZWNpZXNfX0ludGVyY2VwdCArDQogICAgICAgICAgICAgc2lnbWEyX3YNCg0KIyBDYWxjdWxhdGUgaGV0ZXJvZ2VuZWl0eSAoSTIpDQpJMiA8LSBsaXN0KA0KICAgIEkyX3RvdGFsID0gKHZhcl90b3RhbCAtIHNpZ21hMl92KSAvIHZhcl90b3RhbCwgIyBUb3RhbCBoZXRlcm9nZW5laXR5DQogICAgSTJfc3R1ZHkgPSAocG9zdGVyaW9yJHNkX3JlZl9fdHJhaXRfdHlwZWJvZHlfc2l6ZSArICMgSGV0ZXJvZ2VuZWl0eSBleHBsYWluZWQgYnkgc3R1ZHkgZGlmZmVyZW5jZXMNCiAgICAgICAgICAgICAgICBwb3N0ZXJpb3Ikc2RfcmVmX190cmFpdF90eXBlZmVjdW5kaXR5ICsNCiAgICAgICAgICAgICAgICBwb3N0ZXJpb3Ikc2RfcmVmX190cmFpdF90eXBlc3Vydml2YWwpIC8gdmFyX3RvdGFsLA0KICAgIEkyX2V4cCA9IHBvc3RlcmlvciRzZF9leHBlcmltZW50X0lEX19JbnRlcmNlcHQgLyB2YXJfdG90YWwsICMgSGV0ZXJvZ2VuZWl0eSBleHBsYWluZWQgYnkgZXhwZXJpbWVudCBkaWZmZXJlbmNlcw0KICAgIEkyX3NwID0gcG9zdGVyaW9yJHNkX3NwZWNpZXNfX0ludGVyY2VwdCAvIHZhcl90b3RhbCwgIyBIZXRlcm9nZW5laXR5IGV4cGxhaW5lZCBieSBzcGVjaWVzIGRpZmZlcmVuY2VzDQogICAgSTJfcGh5bG8gPSBwb3N0ZXJpb3Ikc2RfcGh5bG9nZW55X19JbnRlcmNlcHQgLyB2YXJfdG90YWwsICMgSGV0ZXJvZ2VuZWl0eSBleHBsYWluZWQgYnkgcGh5bG9nZW5ldGljIHJlbGF0ZWRuZXNzDQogICAgSTJfb2JzID0gcG9zdGVyaW9yJHNkX29ic19fSW50ZXJjZXB0IC8gdmFyX3RvdGFsICMgSGV0ZXJvZ2VuZWl0eSBleHBsYWluZWQgYnkgcmVzaWR1YWwgdmFyaWF0aW9uDQoNCikNCg0KIyBDYWxjdWxhdGUgbWVhbiBhbmQgY3JlZGlibGUgaW50ZXJ2YWxzIA0Kc3VtbWFyeV90YWJsZSA8LSB0KHNhcHBseShJMiwgZnVuY3Rpb24oeCkgew0KICAgIGMoTWVhbiA9IDEwMCpyb3VuZChtZWFuKHgpLDQpLCANCiAgICAgIGAgYCA9IDEwMCogcm91bmQocXVhbnRpbGUoeCwgMC4wMjUpLDQpLCANCiAgICAgIGAgYCA9IDEwMCpyb3VuZChxdWFudGlsZSh4LCAwLjk3NSksNCkpDQp9KSkNCg0KIyBDdXN0b21pc2UgdGFibGUNCnN1bW1hcnlfdGFibGUgPC0gc3VtbWFyeV90YWJsZSAlPiUNCiAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KICAgIHJvd25hbWVzX3RvX2NvbHVtbigiVmFyaWFibGUiKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICAgIFZhcmlhYmxlID0gcmVjb2RlKFZhcmlhYmxlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiSTJfdG90YWwiICA9ICJUb3RhbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJJMl9zdHVkeSIgID0gIlN0dWR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkkyX2V4cCIgICAgPSAiRXhwZXJpbWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJJMl9zcCIgICAgID0gIlNwZWNpZXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiSTJfcGh5bG8iICA9ICJQaHlsb2dlbnkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiSTJfb2JzIiAgICA9ICJSZXNpZHVhbCIpDQogICAgKSAlPiUNCiAgICByZW5hbWUoDQogICAgICAgIGxvd2VyX0hQRCA9IGAgLjIuNSVgLA0KICAgICAgICB1cHBlcl9IUEQgPSBgIC45Ny41JWANCiAgICApICU+JQ0KICBtdXRhdGUoDQogICAgVmFyaWFibGUgPSBwYXN0ZTAoIkk8c3VwPjI8L3N1cD48c3ViPiIsIFZhcmlhYmxlKSAgICMgQ3JlYXRlIGEgbmV3IGNvbHVtbiB3aXRoIGZvcm1hdHRlZCBJwrIgYW5kIHN1YnNjcmlwdHMNCiAgKQ0KDQoNCiMgRGlzcGxheSB0YWJsZQ0Ka2FibGUoc3VtbWFyeV90YWJsZSwgImh0bWwiLCBlc2NhcGUgPSBGQUxTRSwgDQogICAgICBjb2wubmFtZXMgPSBjKCJIZXRlcm9nZW5laXR5ICglKSIsICJNZWFuIiwgIkxvd2VyIEhQRCIsICJVcHBlciBIUEQiKSwNCiAgICAgIGFsaWduID0gYygnbCcsICdyJywgJ3InLCAncicpKSAlPiUNCiAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImNlbnRlciIsIGZpeGVkX3RoZWFkID0gVFJVRSkgJT4lDQogIGNvbHVtbl9zcGVjKDEsIHdpZHRoID0gIjIwMHB4IiwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCg0KIyMjIyAqRGF0YSB2aXN1YWxpc2F0aW9uKg0KYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0PTd9DQojIEdlbmVyYXRlIHByZWRpY3Rpb25zDQplbW1lYW5zX292ZXJhbGwgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKGxuUlJfbW9kZWxfb3ZlcmFsbCwgfiB0cmFpdF90eXBlKSkNCg0KZW1tZWFuc19vdmVyYWxsJHRyYWl0X3R5cGUgPC0gZmFjdG9yKGVtbWVhbnNfb3ZlcmFsbCR0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYm9keV9zaXplIiwgImZlY3VuZGl0eSIsICJzdXJ2aXZhbCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQm9keSBzaXplIiwgIkZlY3VuZGl0eSIsICJTdXJ2aXZhbCIpKQ0KDQojIENhbGN1bGF0ZSBzYW1wbGUgc2l6ZXMgYW5kIHN0dWR5IGNvdW50cw0Kc2FtcGxlX3NpemVzX3RyYWl0cyA8LSBkYXRhICU+JQ0KICBncm91cF9ieSh0cmFpdF90eXBlKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGVzdGltYXRlcyA9IG4oKSwNCiAgICBzdHVkaWVzID0gbl9kaXN0aW5jdChyZWYpDQogICkNCg0KIyBQbG90DQpnZ3Bsb3QoKSArDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgIyBIb3Jpem9udGFsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSwgDQogICAgICAgICAgICAgICBsd2Q9MSkgKw0KICAgIGdlb21fcXVhc2lyYW5kb20oZGF0YSA9IGRhdGEsICMgUGxvdCBlZmZlY3Qgc2l6ZXMsIHNjYWxlZCBieSBwcmVjaXNpb24NCiAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGxuUlIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxL3NxcnQodmFyX2xuUlIpKSwgDQogICAgICAgICAgICAgICAgICAgICBmaWxsID0gImdyYXk3NSIsDQogICAgICAgICAgICAgICAgICAgICBzaGFwZSA9IDIxLA0KICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSAwLjI1LCANCiAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gMC4yKSArDQogICAgZ2VvbV9lcnJvcmJhcihkYXRhID0gZW1tZWFuc19vdmVyYWxsLCAgICMgUGxvdCB0aGUgcG9pbnQgZXN0aW1hdGVzIGluIHdoaXRlIGZvciBiYWNrZ3JvdW5kDQogICAgICAgICAgICAgICAgICBhZXMoeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCwNCiAgICAgICAgICAgICAgICAgICAgICB4ID0gdHJhaXRfdHlwZSksIA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIsDQogICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMDg1LA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSAid2hpdGUiKSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gZW1tZWFuc19vdmVyYWxsLCAjIFBsb3QgdGhlIGNyZWRpYmxlIGludGVydmFscyBpbiB3aGl0ZSBmb3IgYmFja2dyb3VuZA0KICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICB5ID0gZW1tZWFuKSwNCiAgICAgICAgICAgICAgIHNpemUgPSA0LjUsIA0KICAgICAgICAgICAgICAgc3Ryb2tlID0gMS41LA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgIGNvbG9yPSJ3aGl0ZSIsDQogICAgICAgICAgICAgICBmaWxsID0gIndoaXRlIikgKw0KICAgIGdlb21fZXJyb3JiYXIoZGF0YSA9IGVtbWVhbnNfb3ZlcmFsbCwgICMgUGxvdCB0aGUgcG9pbnQgZXN0aW1hdGVzIA0KICAgICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBEKSwgDQogICAgICAgICAgICAgICAgICBzaXplID0gMS41LA0KICAgICAgICAgICAgICAgICAgd2lkdGggPSAwLjA3NSwNCiAgICAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIikgKw0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGVtbWVhbnNfb3ZlcmFsbCwgIyBQbG90IHRoZSBjcmVkaWJsZSBpbnRlcnZhbHMNCiAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgeSA9IGVtbWVhbiksDQogICAgICAgICAgICAgICBzaXplID0gNCwNCiAgICAgICAgICAgICAgIHNoYXBlID0gMjEsDQogICAgICAgICAgICAgICBzdHJva2UgPSAxLjUsDQogICAgICAgICAgICAgICBjb2xvcj0iYmxhY2siLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJ3aGl0ZSIpICsNCiAgICBnZW9tX3RleHQoZGF0YSA9IHNhbXBsZV9zaXplc190cmFpdHMsICAjIFNhbXBsZSBzaXplIGFubm90YXRpb25zIA0KICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgeSA9IDEuNSwNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpKSwgDQogICAgICAgICAgICAgIGhqdXN0ID0gMSwgc2l6ZSA9IDUsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgICB0aGVtZV9idygpICsgICAgICMgQ3VzdG9taXplIHRoZSBwbG90DQogICAgbGFicyh5ID0gImxuUlIiLCB4ID0gIiIpICsNCiAgICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDIsIDgpKSsgDQogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpKSArDQogICAgZ3VpZGVzKGNvbG9yID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICBjb29yZF9mbGlwKCkgKyANCiAgICB5bGltKC0xLjUsIDEuNSkNCg0KIyBTYXZlIGZpZ3VyZQ0KZ2dzYXZlKGZpbGUgPSAiZmlnL2xuUlJfb3ZlcmFsbC5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA3LCBkcGkgPSA1MDApDQpgYGANCg0KIyMjICoqVGVtcGVyYXR1cmUgcmVnaW1lKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5SUiB+IHRyYWl0X3R5cGU6d2FybV9jb2xkIC0xICsgIyBTZXBhcmF0ZSBlZmZlY3RzIGJ5IHRyYWl0IHR5cGUNCiAgICAgICAgICAgICAgICAodHJhaXRfdHlwZS0xfHJlZikgKyAjIENvcnJlbGF0aW9uIGJldHdlZW4gdHJhaXRzIGFtb25nIHN0dWRpZXMNCiAgICAgICAgICAgICAgICAoMXxzcGVjaWVzKSArICMgU3BlY2llcy1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8Z3IocGh5bG9nZW55LCBjb3YgPSBwaHlsb19tYXRyaXgpKSArICMgUGh5bG9nZW5ldGljIHJlbGF0ZWRuZXNzDQogICAgICAgICAgICAgICAgKDF8ZXhwZXJpbWVudF9JRCkgKyAjIEV4cGVyaW1lbnQtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfG9icykgKyAjIE9ic2VydmF0aW9uLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICBmY29yKFZDVl9sblJSKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5SUl9tb2RlbF93YXJtX2NvbGQgPC0gYnJtKGZvcm11bGEsIA0KICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gZ2F1c3NpYW4oKSwNCiAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLCANCiAgICAgICAgICAgICAgICAgIGRhdGEyID0gbGlzdChwaHlsb19tYXRyaXggPSBwaHlsb19tYXRyaXgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVkNWX2xuUlIgPSBWQ1ZfbG5SUiksDQogICAgICAgICAgICAgICAgICBwcmlvciA9IHByaW9yLA0KICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTUpLA0KICAgICAgICAgICAgICAgICAgaXRlciA9IDQwMDAsIA0KICAgICAgICAgICAgICAgICAgd2FybXVwID0gMjAwMCwNCiAgICAgICAgICAgICAgICAgIGNoYWlucyA9IDQsIA0KICAgICAgICAgICAgICAgICAgY29yZXMgPSA0LCANCiAgICAgICAgICAgICAgICAgIHNlZWQgPSAxMjMpIA0KDQojIFNhdmUgbW9kZWwNCnNhdmVSRFMobG5SUl9tb2RlbF93YXJtX2NvbGQsIGZpbGUgPSAiUkRhdGEvbG5SUl9tb2RlbF93YXJtX2NvbGQucmRzIikNCmBgYA0KDQojIyMjICpNb2RlbCBvdXRwdXQqDQpgYGB7cn0NCiMgTG9hZCBtb2RlbA0KbG5SUl9tb2RlbF93YXJtX2NvbGQgPC0gcmVhZFJEUygiUkRhdGEvbG5SUl9tb2RlbF93YXJtX2NvbGQucmRzIikNCg0KIyBEaXNwbGF5IG1vZGVsIG91dHB1dCANCnN1bW1hcnkobG5SUl9tb2RlbF93YXJtX2NvbGQpDQoNCiMgQ2xlYW5lZCBtb2RlbCBvdXRwdXQNCmFzLmRhdGEuZnJhbWUoZml4ZWYobG5SUl9tb2RlbF93YXJtX2NvbGQsIHN1bW1hcnkgPSBUUlVFKSkgJT4lDQogICMgUmVuYW1lIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBmb3IgY2xlYW5lciBkaXNwbGF5DQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAiUGFyYW1ldGVyIikgJT4lIA0KICBtdXRhdGUoDQogICAgIyBTaW1wbGlmeSBgdHJhaXRfdHlwZWAgYW5kIGB3YXJtX2NvbGRgIGludGVyYWN0aW9ucw0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKyk6d2FybV9jb2xkKGNvbGR8d2FybSkiLCAiXFwxKFxcMikiLCBQYXJhbWV0ZXIpDQogICkgJT4lDQogICMgUm91bmQgbnVtYmVycyB0byAzIGRlY2ltYWwgcG9pbnRzDQogIG11dGF0ZShhY3Jvc3MoYyhFc3RpbWF0ZSwgUTIuNSwgUTk3LjUpLCB+IHJvdW5kKC4sIDMpKSkgJT4lDQogIHNlbGVjdChQYXJhbWV0ZXIsIEVzdGltYXRlLCBgTG93ZXIgQ0lgID0gUTIuNSwgYFVwcGVyIENJYCA9IFE5Ny41KSAlPiUNCiAga2FibGUoKSAlPiUNCiAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImNlbnRlciIsIGZpeGVkX3RoZWFkID0gVFJVRSkgJT4lDQogIGNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFLCBib3JkZXJfcmlnaHQgPSBUUlVFKSAlPiUNCiAgcm93X3NwZWMoMCwgYmFja2dyb3VuZCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIiwgYm9sZCA9IFRSVUUpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZpeGVkX3RoZWFkID0gVFJVRSkNCmBgYA0KDQojIyMjICpDb250cmFzdHMqIA0KYGBge3J9DQojIEdlbmVyYXRlIHByZWRpY3Rpb25zDQplbW1zIDwtIGVtbWVhbnMobG5SUl9tb2RlbF93YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgIHNwZWNzID0gfiB3YXJtX2NvbGQgfCB0cmFpdF90eXBlKQ0KDQojIEdlbmVyYXRlIGNvbnRyYXN0cw0KY29udHJhc3QoZW1tcywgbWV0aG9kID0gInBhaXJ3aXNlIikNCmBgYA0KDQojIyMjICpEYXRhIHZpc3VhbGlzYXRpb24qDQpgYGB7ciwgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQ9N30NCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbWVhbnNfd2FybV9jb2xkIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucyhsblJSX21vZGVsX3dhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlY3MgPSB+IHdhcm1fY29sZCB8IHRyYWl0X3R5cGUpKQ0KDQplbW1lYW5zX3dhcm1fY29sZCR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX3dhcm1fY29sZCR0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYm9keV9zaXplIiwgImZlY3VuZGl0eSIsICJzdXJ2aXZhbCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQm9keSBzaXplIiwgIkZlY3VuZGl0eSIsICJTdXJ2aXZhbCIpKQ0KDQplbW1lYW5zX3dhcm1fY29sZCR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfd2FybV9jb2xkJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgQ2FsY3VsYXRlIHNhbXBsZSBzaXplcyBhbmQgc3R1ZHkgY291bnRzDQpzYW1wbGVfc2l6ZXMgPC0gZGF0YSAlPiUNCiAgZ3JvdXBfYnkodHJhaXRfdHlwZSwgd2FybV9jb2xkKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGVzdGltYXRlcyA9IG4oKSwNCiAgICBzdHVkaWVzID0gbl9kaXN0aW5jdChyZWYpDQogICkNCg0KIyBQbG90DQpnZ3Bsb3QoKSArDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgIyBIb3Jpem9udGFsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSwgDQogICAgICAgICAgICAgICBsd2Q9MSkgKw0KICAgIGdlb21fcXVhc2lyYW5kb20oZGF0YSA9IGRhdGEsICAgICAjIFBsb3QgZWZmZWN0IHNpemVzLCBzY2FsZWQgYnkgcHJlY2lzaW9uDQogICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5SUiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMS9zcXJ0KHZhcl9sblJSKSksIA0KICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLA0KICAgICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4yNSwgDQogICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuMykgKw0KICAgIGdlb21fZXJyb3JiYXIoZGF0YSA9IGVtbWVhbnNfd2FybV9jb2xkLCAgIyBQbG90IHRoZSBwb2ludCBlc3RpbWF0ZXMgaW4gd2hpdGUgZm9yIGJhY2tncm91bmQNCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTp3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQpLCANCiAgICAgICAgICAgICAgICAgIGNvbG9yPSJ3aGl0ZSIsDQogICAgICAgICAgICAgICAgICBzaXplID0gMi41LA0KICAgICAgICAgICAgICAgICAgd2lkdGggPSAwLjE3KSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gZW1tZWFuc193YXJtX2NvbGQsICAjIFBsb3QgdGhlIGNyZWRpYmxlIGludGVydmFscyBpbiB3aGl0ZSBmb3IgYmFja2dyb3VuZA0KICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgeSA9IGVtbWVhbiksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDQsIA0KICAgICAgICAgICAgICAgc3Ryb2tlID0gMiwNCiAgICAgICAgICAgICAgIGNvbG9yPSJ3aGl0ZSIsDQogICAgICAgICAgICAgICBmaWxsID0gIndoaXRlIikgKw0KICAgIGdlb21fZXJyb3JiYXIoZGF0YSA9IGVtbWVhbnNfd2FybV9jb2xkLCAjIFBsb3QgdGhlIHBvaW50IGVzdGltYXRlcyANCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTp3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQpLCANCiAgICAgICAgICAgICAgICAgIGNvbG9yPSJibGFjayIsDQogICAgICAgICAgICAgICAgICBzaXplID0gMiwNCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4xNSkgKw0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGVtbWVhbnNfd2FybV9jb2xkLCAjIFBsb3QgdGhlIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgeSA9IGVtbWVhbiksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDMuNSwgDQogICAgICAgICAgICAgICBzdHJva2UgPSAyLA0KICAgICAgICAgICAgICAgY29sb3I9ImJsYWNrIiwNCiAgICAgICAgICAgICAgIGZpbGwgPSAid2hpdGUiKSArDQogICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXMsICAjIFNhbXBsZSBzaXplIGFubm90YXRpb25zIA0KICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgIHkgPSAxLjUsDQogICAgICAgICAgICAgICAgICBsYWJlbCA9IHBhc3RlMCgiayA9ICIsIGVzdGltYXRlcywgIiAoIiwgc3R1ZGllcywgIikiKSwNCiAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgIGhqdXN0ID0gMSwgc2l6ZSA9IDUsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgICB0aGVtZV9idygpICsgICAgICMgQ3VzdG9taXplIHRoZSBwbG90DQogICAgbGFicyh5ID0gImxuUlIiLCB4ID0gIiIpICsNCiAgICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDIsIDgpKSsgDQojICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNBNUY4MjAiLCAiIzczQjcwNiIsICAiIzlDRUZGQyIsICIjMDZBMkJBIiwgICIjRkVEMkVEIiwgIiNCOTA2NzQiKSkrDQogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IiwgIiMwNkI0QkEiLCAiI0U4MDc1NiIsICIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIkNvbGQiID0gIiMwNkI0QkEiLCAiV2FybSIgPSAiI0U4MDc1NiIpKSArICAjIFRleHQgY29sb3VyDQogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpKSArDQogICAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIHNpemUgPSAibm9uZSIpKw0KICAgIGNvb3JkX2ZsaXAoKSArIA0KICAgIHlsaW0oLTEuNSwgMS41KQ0KDQpnZ3NhdmUoZmlsZSA9ICJmaWcvbG5SUl93YXJtX2NvbGQucG5nIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNywgZHBpID0gNTAwKQ0KYGBgDQoNCiMjIyAqKkFzc2F5IHRlbXBlcmF0dXJlIGRpZmZlcmVuY2UqKiANCg0KV2UgY2FsY3VsYXRlZCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBhc3NheSB0ZW1wZXJhdHVyZSBhbmQgY29udHJvbCB0ZW1wZXJhdHVyZSAoYXNzYXlfdGVtcF9kaWZmKSB0byBhY2NvdW50IGZvciB0aGUgZmFjdCB0aGF0IGFuaW1hbHMgd2VyZSB0ZXN0ZWQgdG8gYSBkaWZmZXJlbnQgcmFuZ2Ugb2YgdGVtcGVyYXR1cmVzLiBXZSBhbHNvIHByZWRpY3RlZCB0aGF0IGVmZmVjdHMgd2lsbCB2YXJ5IGlmIHRyYWl0cyBhcmUgYXNzYXllZCBhdCBjb2xkZXItIG9yIHdhcm1lci10aGFuLWNvbnRyb2wgY29uZGl0aW9ucywgZGVwZW5kaW5nIG9uIHRoZSB0ZW1wZXJhdHVyZSByZWdpbWUuIA0KQmVjYXVzZSB0aGUgdmFyaWF0aW9uIGluIGFzc2F5IHRlbXBlcmF0dXJlIGdlbmVyYXRlcyBzb21lIG51aXNhbmNlIGhldGVyb2dlbmVpdHkgKHNlbnN1IE5vYmxlIGV0IGFsLiwgMjAxNyksIHRoZSByZXN1bHRzIG9mIHN1YnNlcXVlbnQgbW9kZWxzIHdlcmUgcHJvdmlkZWQgYWZ0ZXIgY29udHJvbGxpbmcgZm9yIGFzc2F5IHRlbXBlcmF0dXJlIGRpZmZlcmVuY2VzLiBJbiBvcmRlciB3b3JkcywgdGhlIHJlc3VsdHMgb2YgYWxsIG1vZGVyYXRvcnMgYXJlIGNvbmRpdGlvbmFsIG9uIGFzc2F5IHRlbXBlcmF0dXJlLCBtZWFuaW5nIHRoYXQgcmVzdWx0cyBhcmUgaW50ZXJwcmV0YWJsZSBhcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGNvbnRyb2wgYW5kIHNlbGVjdGVkIGxpbmVzLCB3aGVuIGFuaW1hbHMgYXJlIHRlc3RlZCBhdCB0aGUgY29udHJvbCB0ZW1wZXJhdHVyZS4gDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5SUiB+IDAgKyB0cmFpdF90eXBlOndhcm1fY29sZCArIHRyYWl0X3R5cGU6d2FybV9jb2xkOmFzc2F5X3RlbXBfZGlmZiArICMgU2VwYXJhdGUgZWZmZWN0cyBieSB0cmFpdCB0eXBlDQogICAgICAgICAgICAgICAgKHRyYWl0X3R5cGUtMXxyZWYpICsgIyBDb3JyZWxhdGlvbiBiZXR3ZWVuIHRyYWl0cyBhbW9uZyBzdHVkaWVzDQogICAgICAgICAgICAgICAgKDF8c3BlY2llcykgKyAjIFNwZWNpZXMtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfGdyKHBoeWxvZ2VueSwgY292ID0gcGh5bG9fbWF0cml4KSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5SUikpICMgVmFyaWFuY2UgY292YXJpYW5jZSBtYXRpeCBvZiBjb3JyZWxhdGVkIHNhbXBsaW5nIHZhcmlhbmNlcw0KDQojIERlZmluZSBwcmlvcnMNCnByaW9yID0gYygNCiAgcHJpb3IoY29uc3RhbnQoMSksIGNsYXNzID0gInNpZ21hIikNCikgIyBCZWNhdXNlIHRoZSByZXNpZHVhbCB2YXJpYW5jZS1jb3ZhcmlhbmNlIHN0cnVjdHVyZSBpcyBzcGVjaWZpZWQgaW4gZmNvciwgdGhlcmUgaXMgbm8gbmVlZCB0byBlc3RpbWF0ZSBzaWdtYSBzbyBpdCBpcyBsZWZ0IGFzIGEgY29uc3RhbnQNCg0KIyBGaXQgbW9kZWwNCmxuUlJfbW9kZWxfYXNzYXlfdGVtcF9kaWZmIDwtIGJybShmb3JtdWxhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBnYXVzc2lhbigpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhMiA9IGxpc3QocGh5bG9fbWF0cml4ID0gcGh5bG9fbWF0cml4LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWQ1ZfbG5SUiA9IFZDVl9sblJSKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmlvciA9IHByaW9yLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OSwgbWF4X3RyZWVkZXB0aCA9IDE1KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyID0gNDAwMCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FybXVwID0gMjAwMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFpbnMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JlcyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZWQgPSAxMjMpIA0KDQojIFNhdmUgbW9kZWwNCnNhdmVSRFMobG5SUl9tb2RlbF9hc3NheV90ZW1wX2RpZmYsIGZpbGUgPSAiUkRhdGEvbG5SUl9tb2RlbF9hc3NheV90ZW1wX2RpZmYucmRzIikNCmBgYA0KDQojIyMjICpNb2RlbCBvdXRwdXQqDQpgYGB7cn0NCiMgTG9hZCBtb2RlbA0KbG5SUl9tb2RlbF9hc3NheV90ZW1wX2RpZmYgPC0gcmVhZFJEUygiUkRhdGEvbG5SUl9tb2RlbF9hc3NheV90ZW1wX2RpZmYucmRzIikNCg0KIyBEaXNwbGF5IG1vZGVsIG91dHB1dCANCnN1bW1hcnkobG5SUl9tb2RlbF9hc3NheV90ZW1wX2RpZmYpDQoNCiMgQ2xlYW5lZCBtb2RlbCBvdXRwdXQNCmFzLmRhdGEuZnJhbWUoZml4ZWYobG5SUl9tb2RlbF9hc3NheV90ZW1wX2RpZmYsIHN1bW1hcnkgPSBUUlVFKSkgJT4lDQogICMgUmVuYW1lIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBmb3IgY2xlYW5lciBkaXNwbGF5DQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAiUGFyYW1ldGVyIikgJT4lIA0KICBtdXRhdGUoDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKTp3YXJtX2NvbGQoY29sZHx3YXJtKSIsICJcXDEoXFwyKSIsIFBhcmFtZXRlciksDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKVxcKHdhcm1cXCk6YXNzYXlfdGVtcF9kaWZmIiwgIlxcMSh3YXJtKTogYXNzYXlfdGVtcF9kaWZmIiwgUGFyYW1ldGVyKQ0KICApICU+JQ0KICAjIFJvdW5kIG51bWJlcnMgdG8gMyBkZWNpbWFsIHBvaW50cw0KICBtdXRhdGUoYWNyb3NzKGMoRXN0aW1hdGUsIFEyLjUsIFE5Ny41KSwgfiByb3VuZCguLCAzKSkpICU+JQ0KICBzZWxlY3QoUGFyYW1ldGVyLCBFc3RpbWF0ZSwgYExvd2VyIENJYCA9IFEyLjUsIGBVcHBlciBDSWAgPSBROTcuNSkgJT4lDQogIGthYmxlKCkgJT4lDQogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBwb3NpdGlvbiA9ICJjZW50ZXIiLCBmaXhlZF90aGVhZCA9IFRSVUUpICU+JQ0KICBjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSwgYm9yZGVyX3JpZ2h0ID0gVFJVRSkgJT4lDQogIHJvd19zcGVjKDAsIGJhY2tncm91bmQgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIsIGJvbGQgPSBUUlVFKSAlPiUNCiAga2FibGVfc3R5bGluZyhmaXhlZF90aGVhZCA9IFRSVUUpDQpgYGANCg0KIyMjIyAqRGF0YSB2aXN1YWxpc2F0aW9uKg0KDQpgYGB7ciwgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQ9MTB9DQojIEdlbmVyYXRlIHByZWRpY3Rpb25zDQplbW1lYW5zX2Fzc2F5X3RlbXBfZGlmZiA8LSBhcy5kYXRhLmZyYW1lKGVtbWVhbnMoDQogIGxuUlJfbW9kZWxfYXNzYXlfdGVtcF9kaWZmLA0KICBzcGVjcyA9IH4gYXNzYXlfdGVtcF9kaWZmIHwgdHJhaXRfdHlwZSAqIHdhcm1fY29sZCwNCiAgYXQgPSBsaXN0KGFzc2F5X3RlbXBfZGlmZiA9IHNlcShtaW4oZGF0YSRhc3NheV90ZW1wX2RpZmYpLCBtYXgoZGF0YSRhc3NheV90ZW1wX2RpZmYpLCBieSA9IDAuNSkpKQ0KICApDQoNCiMgQ2FsY3VsYXRlIHJhbmdlIG9mIHZhbHVlcyBmb3IgZWFjaCBjYXRlZ29yeQ0KcmFuZ2VfZGYgPC0gZGF0YSAlPiUNCiAgZ3JvdXBfYnkodHJhaXRfdHlwZSwgd2FybV9jb2xkKSAlPiUNCiAgc3VtbWFyaXplKA0KICAgIG1pbl9hc3NheV90ZW1wX2RpZmYgPSBtaW4oYXNzYXlfdGVtcF9kaWZmKSwNCiAgICBtYXhfYXNzYXlfdGVtcF9kaWZmID0gbWF4KGFzc2F5X3RlbXBfZGlmZikNCiAgKQ0KDQplbW1lYW5zX2Fzc2F5X3RlbXBfZGlmZiR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX2Fzc2F5X3RlbXBfZGlmZiR0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYm9keV9zaXplIiwgImZlY3VuZGl0eSIsICJzdXJ2aXZhbCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQm9keSBzaXplIiwgIkZlY3VuZGl0eSIsICJTdXJ2aXZhbCIpKQ0KDQplbW1lYW5zX2Fzc2F5X3RlbXBfZGlmZiR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfYXNzYXlfdGVtcF9kaWZmJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgVGFpbG9yIHByZWRpY3Rpb25zIHRvIHRoZSByYW5nZSBvZiB0aGUgZGF0YQ0KZW1tZWFuc19hc3NheV90ZW1wX2RpZmYgPC0gZW1tZWFuc19hc3NheV90ZW1wX2RpZmYgJT4lDQogIGxlZnRfam9pbihyYW5nZV9kZiwgYnkgPSBjKCJ0cmFpdF90eXBlIiwgIndhcm1fY29sZCIpKSAlPiUNCiAgZmlsdGVyKA0KICAgIGFzc2F5X3RlbXBfZGlmZiA+PSBtaW5fYXNzYXlfdGVtcF9kaWZmLA0KICAgIGFzc2F5X3RlbXBfZGlmZiA8PSBtYXhfYXNzYXlfdGVtcF9kaWZmDQogICkNCg0KIyBQbG90DQpnZ3Bsb3QoKSArIA0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUpICsgIA0KICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsICMgVmVydGljYWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArICANCiAgICBnZW9tX3BvaW50KGRhdGEgPSBkYXRhLCAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBhc3NheV90ZW1wX2RpZmYsIA0KICAgICAgICAgICAgICAgICAgICAgIHkgPSBsblJSLCANCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMS9zcXJ0KHZhcl9sblJSKSwgDQogICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwgDQogICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNywgDQogICAgICAgICAgICAgICAgICBzdHJva2UgPSAxLA0KICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjA1KSkgKyANCiAgICAgZ2VvbV9yaWJib24oZGF0YSA9IGVtbWVhbnNfYXNzYXlfdGVtcF9kaWZmLCAjIFNoYWRlZCBhcmVhIGZvciBjcmVkaWJsZSBpbnRlcnZhbHMNCiAgICAgICAgICAgICAgICAgYWVzKHggPSBhc3NheV90ZW1wX2RpZmYsDQogICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgIGFscGhhID0gLjUpICsgDQogICAgIGdlb21fbGluZShkYXRhID0gZW1tZWFuc19hc3NheV90ZW1wX2RpZmYsICAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSBhc3NheV90ZW1wX2RpZmYsDQogICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsgDQogICAgICBnZW9tX3RleHQoZGF0YSA9IHNhbXBsZV9zaXplcywgDQogICAgICAgICAgICAgIGFlcyh4ID0gSW5mLCANCiAgICAgICAgICAgICAgICAgIHkgPSBpZmVsc2Uod2FybV9jb2xkID09ICJXYXJtIiwgLTAuOSwgLTEuMyksICAjIFNhbXBsZSBzaXplcw0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEuMDUsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIA0KICBmYWNldF93cmFwKH4gdHJhaXRfdHlwZSwgbmNvbCA9IDEpICsgIyBEaWZmZXJlbnQgcGFuZWxzIGZvciBlYWNoIHRyYWl0DQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgbGFicyh4ID0gIkFzc2F5IHRlbXBlcmF0dXJlIGRpZmZlcmVuY2UiLCB5ID0gImxuUlIiLCBjb2wgPSAiUmVnaW1lIikgKw0KICB0aGVtZV9idygpICsgDQogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgOCkpKyANCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjUsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxOCksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAyMikpICsNCiAgICBndWlkZXMoZmlsbCA9ICJub25lIiwgc2l6ZSA9ICJub25lIikrDQogICAgeWxpbSgtMS41LCAxLjUpDQoNCmdnc2F2ZShmaWxlID0gImZpZy9sblJSX2Fzc2F5X3RlbXBfZGlmZi5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSAxMCwgZHBpID0gNTAwKQ0KYGBgDQoNCiMjIyAqKlNlbGVjdGlvbiB0ZW1wZXJhdHVyZSoqIA0KDQojIyMjICpNb2RlbCBzcGVjaWZpY2F0aW9uKg0KYGBge3IsIGV2YWwgPSBGfQ0KIyBNb2RlbCBzcGVjaWZpY2F0aW9uDQpmb3JtdWxhIDwtIGJmKGxuUlIgfiAwICsgdHJhaXRfdHlwZTp3YXJtX2NvbGQgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICB0cmFpdF90eXBlOndhcm1fY29sZDphc3NheV90ZW1wX2RpZmYgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICB0cmFpdF90eXBlOndhcm1fY29sZDpzZWxlY3RfdGVtcF9kaWZmICsgIyBTZXBhcmF0ZSBlZmZlY3RzIGJ5IHRyYWl0IHR5cGUNCiAgICAgICAgICAgICAgICAodHJhaXRfdHlwZS0xfHJlZikgKyAjIENvcnJlbGF0aW9uIGJldHdlZW4gdHJhaXRzIGFtb25nIHN0dWRpZXMNCiAgICAgICAgICAgICAgICAoMXxzcGVjaWVzKSArICMgU3BlY2llcy1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8Z3IocGh5bG9nZW55LCBjb3YgPSBwaHlsb19tYXRyaXgpKSArICMgUGh5bG9nZW5ldGljIHJlbGF0ZWRuZXNzDQogICAgICAgICAgICAgICAgKDF8ZXhwZXJpbWVudF9JRCkgKyAjIEV4cGVyaW1lbnQtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfG9icykgKyAjIE9ic2VydmF0aW9uLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICBmY29yKFZDVl9sblJSKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5SUl9tb2RlbF9zZWxfdGVtcF9kaWZmIDwtIGJybShmb3JtdWxhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gZ2F1c3NpYW4oKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhMiA9IGxpc3QocGh5bG9fbWF0cml4ID0gcGh5bG9fbWF0cml4LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVkNWX2xuUlIgPSBWQ1ZfbG5SUiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yID0gcHJpb3IsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OSwgbWF4X3RyZWVkZXB0aCA9IDE1KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDQwMDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXJtdXAgPSAyMDAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFpbnMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEyMykgDQoNCiMgU2F2ZSBtb2RlbA0Kc2F2ZVJEUyhsblJSX21vZGVsX3NlbF90ZW1wX2RpZmYsIGZpbGUgPSAiUkRhdGEvbG5SUl9tb2RlbF9zZWxfdGVtcF9kaWZmLnJkcyIpDQpgYGANCg0KIyMjIyAqTW9kZWwgb3V0cHV0Kg0KYGBge3J9DQojIExvYWQgbW9kZWwNCmxuUlJfbW9kZWxfc2VsX3RlbXBfZGlmZiA8LSByZWFkUkRTKCJSRGF0YS9sblJSX21vZGVsX3NlbF90ZW1wX2RpZmYucmRzIikNCg0KIyBEaXNwbGF5IG1vZGVsIG91dHB1dCANCnN1bW1hcnkobG5SUl9tb2RlbF9zZWxfdGVtcF9kaWZmKQ0KDQojIENsZWFuZWQgbW9kZWwgb3V0cHV0DQphcy5kYXRhLmZyYW1lKGZpeGVmKGxuUlJfbW9kZWxfc2VsX3RlbXBfZGlmZiwgc3VtbWFyeSA9IFRSVUUpKSAlPiUNCiAgIyBSZW5hbWUgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGZvciBjbGVhbmVyIGRpc3BsYXkNCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJQYXJhbWV0ZXIiKSAlPiUgDQogIG11dGF0ZSgNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspOndhcm1fY29sZChjb2xkfHdhcm0pIiwgIlxcMShcXDIpIiwgUGFyYW1ldGVyKSwNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspXFwod2FybVxcKTpzZWxlY3RfdGVtcF9kaWZmIiwgIlxcMSh3YXJtKTogc2VsZWN0X3RlbXBfZGlmZiIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkRhdGEgdmlzdWFsaXNhdGlvbioNCg0KYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0PTEwfQ0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucw0KZW1tZWFuc19zZWxfdGVtcF9kaWZmIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5SUl9tb2RlbF9zZWxfdGVtcF9kaWZmLA0KICBzcGVjcyA9IH4gc2VsZWN0X3RlbXBfZGlmZiB8IHRyYWl0X3R5cGUgKiB3YXJtX2NvbGQsDQogIGF0ID0gbGlzdChzZWxlY3RfdGVtcF9kaWZmID0gc2VxKG1pbihkYXRhJHNlbGVjdF90ZW1wX2RpZmYpLCBtYXgoZGF0YSRzZWxlY3RfdGVtcF9kaWZmKSwgYnkgPSAwLjUpLA0KICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID0gMCkpDQogICkgIyBDb25kaXRpb25hbCBlZmZlY3RzIG9uIGFzc2F5X3RlbXBfZGlmZiA9IDANCg0KIyBDYWxjdWxhdGUgcmFuZ2Ugb2YgdmFsdWVzIGZvciBlYWNoIGNhdGVnb3J5DQpyYW5nZV9kZiA8LSBkYXRhICU+JQ0KICBncm91cF9ieSh0cmFpdF90eXBlLCB3YXJtX2NvbGQpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWluX3NlbGVjdF90ZW1wX2RpZmYgPSBtaW4oc2VsZWN0X3RlbXBfZGlmZiksDQogICAgbWF4X3NlbGVjdF90ZW1wX2RpZmYgPSBtYXgoc2VsZWN0X3RlbXBfZGlmZikNCiAgKQ0KDQplbW1lYW5zX3NlbF90ZW1wX2RpZmYkdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19zZWxfdGVtcF9kaWZmJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfc2VsX3RlbXBfZGlmZiR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfc2VsX3RlbXBfZGlmZiR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KDQojIFRhaWxvciBwcmVkaWN0aW9ucyB0byB0aGUgcmFuZ2Ugb2YgdGhlIGRhdGENCmVtbWVhbnNfc2VsX3RlbXBfZGlmZiA8LSBlbW1lYW5zX3NlbF90ZW1wX2RpZmYgJT4lDQogIGxlZnRfam9pbihyYW5nZV9kZiwgYnkgPSBjKCJ0cmFpdF90eXBlIiwgIndhcm1fY29sZCIpKSAlPiUNCiAgZmlsdGVyKA0KICAgIHNlbGVjdF90ZW1wX2RpZmYgPj0gbWluX3NlbGVjdF90ZW1wX2RpZmYsDQogICAgc2VsZWN0X3RlbXBfZGlmZiA8PSBtYXhfc2VsZWN0X3RlbXBfZGlmZg0KICApDQoNCiMgUGxvdA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsICAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBzZWxlY3RfdGVtcF9kaWZmLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5SUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5SUiksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX3NlbF90ZW1wX2RpZmYsICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IHNlbGVjdF90ZW1wX2RpZmYsDQogICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgIGFscGhhID0gLjUpICsgDQogICAgIGdlb21fbGluZShkYXRhID0gZW1tZWFuc19zZWxfdGVtcF9kaWZmLCAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSBzZWxlY3RfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArICANCiAgICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXMsIA0KICAgICAgICAgICAgICBhZXMoeCA9IEluZiwgDQogICAgICAgICAgICAgICAgICB5ID0gaWZlbHNlKHdhcm1fY29sZCA9PSAiV2FybSIsIC0wLjksIC0xLjMpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBmYWNldF93cmFwKH4gdHJhaXRfdHlwZSwgbmNvbCA9IDEpICsgICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJTZWxlY3Rpb24gdGVtcGVyYXR1cmUgZGlmZmVyZW5jZSIsIHkgPSAibG5SUiIsIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCA4KSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNSwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIyKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICB5bGltKC0xLjUsIDEuNSkNCg0KZ2dzYXZlKGZpbGUgPSAiZmlnL2xuUlJfc2VsX3RlbXBfZGlmZi5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA3LCBkcGkgPSA1MDApDQpgYGANCg0KDQojIyMgKipOdW1iZXIgb2YgZ2VuZXJhdGlvbnMgb2Ygc2VsZWN0aW9uKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5SUiB+IDAgKyB0cmFpdF90eXBlOndhcm1fY29sZCArIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOmFzc2F5X3RlbXBfZGlmZiArIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOnNjYWxlKGdlbl9zZWxlY3Rpb24pICsgIyBTZXBhcmF0ZSBlZmZlY3RzIGJ5IHRyYWl0IHR5cGUNCiAgICAgICAgICAgICAgICAodHJhaXRfdHlwZS0xfHJlZikgKyAjIENvcnJlbGF0aW9uIGJldHdlZW4gdHJhaXRzIGFtb25nIHN0dWRpZXMNCiAgICAgICAgICAgICAgICAoMXxzcGVjaWVzKSArICMgU3BlY2llcy1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8Z3IocGh5bG9nZW55LCBjb3YgPSBwaHlsb19tYXRyaXgpKSArICMgUGh5bG9nZW5ldGljIHJlbGF0ZWRuZXNzDQogICAgICAgICAgICAgICAgKDF8ZXhwZXJpbWVudF9JRCkgKyAjIEV4cGVyaW1lbnQtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfG9icykgKyAjIE9ic2VydmF0aW9uLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICBmY29yKFZDVl9sblJSKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5SUl9tb2RlbF9nZW5fc2VsZWN0aW9uIDwtIGJybShmb3JtdWxhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gZ2F1c3NpYW4oKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhMiA9IGxpc3QocGh5bG9fbWF0cml4ID0gcGh5bG9fbWF0cml4LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVkNWX2xuUlIgPSBWQ1ZfbG5SUiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yID0gcHJpb3IsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OSwgbWF4X3RyZWVkZXB0aCA9IDE1KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDQwMDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXJtdXAgPSAyMDAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFpbnMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEyMykgDQojIFNhdmUgbW9kZWwNCnNhdmVSRFMobG5SUl9tb2RlbF9nZW5fc2VsZWN0aW9uLCBmaWxlID0gIlJEYXRhL2xuUlJfbW9kZWxfZ2VuX3NlbGVjdGlvbi5yZHMiKQ0KYGBgDQoNCiMjIyMgKk1vZGVsIG91dHB1dCoNCmBgYHtyfQ0KIyBMb2FkIG1vZGVsDQpsblJSX21vZGVsX2dlbl9zZWxlY3Rpb24gPC0gcmVhZFJEUygiUkRhdGEvbG5SUl9tb2RlbF9nZW5fc2VsZWN0aW9uLnJkcyIpDQoNCiMgRGlzcGxheSBtb2RlbCBvdXRwdXQgDQpzdW1tYXJ5KGxuUlJfbW9kZWxfZ2VuX3NlbGVjdGlvbikNCg0KIyBDbGVhbmVkIG1vZGVsIG91dHB1dA0KYXMuZGF0YS5mcmFtZShmaXhlZihsblJSX21vZGVsX2dlbl9zZWxlY3Rpb24sIHN1bW1hcnkgPSBUUlVFKSkgJT4lDQogICMgUmVuYW1lIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBmb3IgY2xlYW5lciBkaXNwbGF5DQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAiUGFyYW1ldGVyIikgJT4lDQogIG11dGF0ZSgNCiAgICAjIFNpbXBsaWZ5IGB0cmFpdF90eXBlYCBhbmQgYHdhcm1fY29sZGAgaW50ZXJhY3Rpb25zDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKTp3YXJtX2NvbGQoY29sZHx3YXJtKSIsICJcXDEoXFwyKSIsIFBhcmFtZXRlciksDQogICAgIyBBZGp1c3QgZm9yIGFzc2F5X3RlbXBfZGlmZg0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKylcXCgoY29sZHx3YXJtKVxcKTphc3NheV90ZW1wX2RpZmYiLCAiXFwxKFxcMik6IGFzc2F5X3RlbXBfZGlmZiIsIFBhcmFtZXRlciksDQogICAgIyBSZW1vdmUgInNjYWxlIiBmcm9tIGdlbl9zZWxlY3Rpb24NCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJzY2FsZWdlbl9zZWxlY3Rpb24iLCAiZ2VuX3NlbGVjdGlvbiIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkRhdGEgdmlzdWFsaXNhdGlvbioNCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD0xMH0NCg0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucw0KZW1tZWFuc19nZW5fc2VsZWN0aW9uIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5SUl9tb2RlbF9nZW5fc2VsZWN0aW9uLA0KICBzcGVjcyA9IH4gZ2VuX3NlbGVjdGlvbiB8IHRyYWl0X3R5cGUgKiB3YXJtX2NvbGQsDQogIGF0ID0gbGlzdChnZW5fc2VsZWN0aW9uID0gc2VxKG1pbihkYXRhJGdlbl9zZWxlY3Rpb24pLCBtYXgoZGF0YSRnZW5fc2VsZWN0aW9uKSwgYnkgPSAwLjUpLA0KICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID0gMCkpDQogICkgIyBDb25kaXRpb25hbCBlZmZlY3RzIG9uIGFzc2F5X3RlbXBfZGlmZiA9IDANCg0KIyBDYWxjdWxhdGUgcmFuZ2Ugb2YgdmFsdWVzIGZvciBlYWNoIGNhdGVnb3J5DQpyYW5nZV9kZiA8LSBkYXRhICU+JQ0KICBncm91cF9ieSh0cmFpdF90eXBlLCB3YXJtX2NvbGQpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWluX2dlbl9zZWxlY3Rpb24gPSBtaW4oZ2VuX3NlbGVjdGlvbiksDQogICAgbWF4X2dlbl9zZWxlY3Rpb24gPSBtYXgoZ2VuX3NlbGVjdGlvbikNCiAgKQ0KDQplbW1lYW5zX2dlbl9zZWxlY3Rpb24kdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19nZW5fc2VsZWN0aW9uJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfZ2VuX3NlbGVjdGlvbiR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfZ2VuX3NlbGVjdGlvbiR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KDQojIFRhaWxvciBwcmVkaWN0aW9ucyB0byB0aGUgcmFuZ2Ugb2YgdGhlIGRhdGENCmVtbWVhbnNfZ2VuX3NlbGVjdGlvbiA8LSBlbW1lYW5zX2dlbl9zZWxlY3Rpb24gJT4lDQogIGxlZnRfam9pbihyYW5nZV9kZiwgYnkgPSBjKCJ0cmFpdF90eXBlIiwgIndhcm1fY29sZCIpKSAlPiUNCiAgZmlsdGVyKA0KICAgIGdlbl9zZWxlY3Rpb24gPj0gbWluX2dlbl9zZWxlY3Rpb24sDQogICAgZ2VuX3NlbGVjdGlvbiA8PSBtYXhfZ2VuX3NlbGVjdGlvbg0KICApDQoNCiMgUGxvdA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsICAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBnZW5fc2VsZWN0aW9uLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5SUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5SUiksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX2dlbl9zZWxlY3Rpb24sICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IGdlbl9zZWxlY3Rpb24sDQogICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgIGFscGhhID0gLjUpICsgDQogICAgIGdlb21fbGluZShkYXRhID0gZW1tZWFuc19nZW5fc2VsZWN0aW9uLCAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSBnZW5fc2VsZWN0aW9uLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArICANCiAgICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXMsIA0KICAgICAgICAgICAgICBhZXMoeCA9IEluZiwgDQogICAgICAgICAgICAgICAgICB5ID0gaWZlbHNlKHdhcm1fY29sZCA9PSAiV2FybSIsIC0wLjksIC0xLjMpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBmYWNldF93cmFwKH4gdHJhaXRfdHlwZSwgbmNvbCA9IDEpICsgICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJOdW1iZXIgIG9mIGdlbmVyYXRpb25zIG9mIHNlbGVjdGlvbiIsIHkgPSAibG5SUiIsIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCA4KSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNSwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIyKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICB5bGltKC0xLjUsIDEuNSkrDQogICAgeGxpbSgwLCAxNTApDQoNCmdnc2F2ZShmaWxlID0gImZpZy9sblJSX2dlbl9zZWxlY3Rpb24ucG5nIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNywgZHBpID0gNTAwKQ0KYGBgDQoNCiMjIyAqKk51bWJlciBvZiBnZW5lcmF0aW9ucyBvZiBjb21tb24gZ2FyZGVuKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5SUiB+IDAgKyB0cmFpdF90eXBlOndhcm1fY29sZCArIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOmFzc2F5X3RlbXBfZGlmZiArIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOnNjYWxlKGdlbl9jb21tb25fZ2FyZGVuKSArICMgU2VwYXJhdGUgZWZmZWN0cyBieSB0cmFpdCB0eXBlDQogICAgICAgICAgICAgICAgKHRyYWl0X3R5cGUtMXxyZWYpICsgIyBDb3JyZWxhdGlvbiBiZXR3ZWVuIHRyYWl0cyBhbW9uZyBzdHVkaWVzDQogICAgICAgICAgICAgICAgKDF8c3BlY2llcykgKyAjIFNwZWNpZXMtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfGdyKHBoeWxvZ2VueSwgY292ID0gcGh5bG9fbWF0cml4KSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5SUikpICMgVmFyaWFuY2UgY292YXJpYW5jZSBtYXRpeCBvZiBjb3JyZWxhdGVkIHNhbXBsaW5nIHZhcmlhbmNlcw0KDQojIERlZmluZSBwcmlvcnMNCnByaW9yID0gYygNCiAgcHJpb3IoY29uc3RhbnQoMSksIGNsYXNzID0gInNpZ21hIikNCikgIyBCZWNhdXNlIHRoZSByZXNpZHVhbCB2YXJpYW5jZS1jb3ZhcmlhbmNlIHN0cnVjdHVyZSBpcyBzcGVjaWZpZWQgaW4gZmNvciwgdGhlcmUgaXMgbm8gbmVlZCB0byBlc3RpbWF0ZSBzaWdtYSBzbyBpdCBpcyBsZWZ0IGFzIGEgY29uc3RhbnQNCg0KIyBGaXQgbW9kZWwNCmxuUlJfbW9kZWxfZ2VuX2NvbW1vbl9nYXJkZW4gPC0gYnJtKGZvcm11bGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBnYXVzc2lhbigpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEyID0gbGlzdChwaHlsb19tYXRyaXggPSBwaHlsb19tYXRyaXgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWQ1ZfbG5SUiA9IFZDVl9sblJSKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IgPSBwcmlvciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyID0gNDAwMCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm11cCA9IDIwMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYWlucyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JlcyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gMTIzKSANCiMgU2F2ZSBtb2RlbA0Kc2F2ZVJEUyhsblJSX21vZGVsX2dlbl9jb21tb25fZ2FyZGVuLCBmaWxlID0gIlJEYXRhL2xuUlJfbW9kZWxfZ2VuX2NvbW1vbl9nYXJkZW4ucmRzIikNCmBgYA0KDQojIyMjICpNb2RlbCBvdXRwdXQqDQpgYGB7cn0NCiMgTG9hZCBtb2RlbA0KbG5SUl9tb2RlbF9nZW5fY29tbW9uX2dhcmRlbiA8LSByZWFkUkRTKCJSRGF0YS9sblJSX21vZGVsX2dlbl9jb21tb25fZ2FyZGVuLnJkcyIpDQoNCiMgRGlzcGxheSBtb2RlbCBvdXRwdXQgDQpzdW1tYXJ5KGxuUlJfbW9kZWxfZ2VuX2NvbW1vbl9nYXJkZW4pDQoNCiMgQ2xlYW5lZCBtb2RlbCBvdXRwdXQNCmFzLmRhdGEuZnJhbWUoZml4ZWYobG5SUl9tb2RlbF9nZW5fY29tbW9uX2dhcmRlbiwgc3VtbWFyeSA9IFRSVUUpKSAlPiUNCiAgIyBSZW5hbWUgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGZvciBjbGVhbmVyIGRpc3BsYXkNCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJQYXJhbWV0ZXIiKSAlPiUNCiAgbXV0YXRlKA0KICAgICMgU2ltcGxpZnkgYHRyYWl0X3R5cGVgIGFuZCBgd2FybV9jb2xkYCBpbnRlcmFjdGlvbnMNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspOndhcm1fY29sZChjb2xkfHdhcm0pIiwgIlxcMShcXDIpIiwgUGFyYW1ldGVyKSwNCiAgICAjIEFkanVzdCBmb3IgYXNzYXlfdGVtcF9kaWZmDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKVxcKChjb2xkfHdhcm0pXFwpOmFzc2F5X3RlbXBfZGlmZiIsICJcXDEoXFwyKTogYXNzYXlfdGVtcF9kaWZmIiwgUGFyYW1ldGVyKSwNCiAgICAjIFJlbW92ZSAic2NhbGUiIGZyb20gZ2VuX2NvbW1vbl9nYXJkZW4NCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJzY2FsZWdlbl9jb21tb25fZ2FyZGVuIiwgImdlbl9jb21tb25fZ2FyZGVuIiwgUGFyYW1ldGVyKQ0KICApICU+JQ0KICAjIFJvdW5kIG51bWJlcnMgdG8gMyBkZWNpbWFsIHBvaW50cw0KICBtdXRhdGUoYWNyb3NzKGMoRXN0aW1hdGUsIFEyLjUsIFE5Ny41KSwgfiByb3VuZCguLCAzKSkpICU+JQ0KICBzZWxlY3QoUGFyYW1ldGVyLCBFc3RpbWF0ZSwgYExvd2VyIENJYCA9IFEyLjUsIGBVcHBlciBDSWAgPSBROTcuNSkgJT4lDQogIGthYmxlKCkgJT4lDQogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBwb3NpdGlvbiA9ICJjZW50ZXIiLCBmaXhlZF90aGVhZCA9IFRSVUUpICU+JQ0KICBjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSwgYm9yZGVyX3JpZ2h0ID0gVFJVRSkgJT4lDQogIHJvd19zcGVjKDAsIGJhY2tncm91bmQgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIsIGJvbGQgPSBUUlVFKSAlPiUNCiAga2FibGVfc3R5bGluZyhmaXhlZF90aGVhZCA9IFRSVUUpDQpgYGANCg0KIyMjIyAqRGF0YSB2aXN1YWxpc2F0aW9uKg0KYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0PTEwfQ0KDQojIEdlbmVyYXRlIHByZWRpY3Rpb25zDQplbW1lYW5zX2dlbl9jb21tb25fZ2FyZGVuIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5SUl9tb2RlbF9nZW5fY29tbW9uX2dhcmRlbiwNCiAgc3BlY3MgPSB+IGdlbl9jb21tb25fZ2FyZGVuIHwgdHJhaXRfdHlwZSAqIHdhcm1fY29sZCwNCiAgYXQgPSBsaXN0KGdlbl9jb21tb25fZ2FyZGVuID0gc2VxKG1pbihkYXRhJGdlbl9jb21tb25fZ2FyZGVuKSwgbWF4KGRhdGEkZ2VuX2NvbW1vbl9nYXJkZW4pLCBieSA9IDEpLA0KICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID0gMCkpDQogICkgIyBDb25kaXRpb25hbCBlZmZlY3RzIG9uIGFzc2F5X3RlbXBfZGlmZiA9IDANCg0KDQojIENhbGN1bGF0ZSByYW5nZSBvZiB2YWx1ZXMgZm9yIGVhY2ggY2F0ZWdvcnkNCnJhbmdlX2RmIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtaW5fZ2VuX2NvbW1vbl9nYXJkZW4gPSBtaW4oZ2VuX2NvbW1vbl9nYXJkZW4pLA0KICAgIG1heF9nZW5fY29tbW9uX2dhcmRlbiA9IG1heChnZW5fY29tbW9uX2dhcmRlbikNCiAgKQ0KDQplbW1lYW5zX2dlbl9jb21tb25fZ2FyZGVuJHRyYWl0X3R5cGUgPC0gZmFjdG9yKGVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4kdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KZW1tZWFuc19nZW5fY29tbW9uX2dhcmRlbiR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4kd2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiY29sZCIsICJ3YXJtIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJDb2xkIiwgIldhcm0iKSkNCg0KIyBUYWlsb3IgcHJlZGljdGlvbnMgdG8gdGhlIHJhbmdlIG9mIHRoZSBkYXRhDQplbW1lYW5zX2dlbl9jb21tb25fZ2FyZGVuIDwtIGVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4gJT4lDQogIGxlZnRfam9pbihyYW5nZV9kZiwgYnkgPSBjKCJ0cmFpdF90eXBlIiwgIndhcm1fY29sZCIpKSAlPiUNCiAgZmlsdGVyKA0KICAgIGdlbl9jb21tb25fZ2FyZGVuID49IG1pbl9nZW5fY29tbW9uX2dhcmRlbiwNCiAgICBnZW5fY29tbW9uX2dhcmRlbiA8PSBtYXhfZ2VuX2NvbW1vbl9nYXJkZW4NCiAgKQ0KDQojIFBsb3QNCmdncGxvdCgpICsgDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgIyBIb3Jpem9udGFsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSkgKyANCiAgICBnZW9tX3BvaW50KGRhdGEgPSBkYXRhLCAgIyBFZmZlY3Qgc2l6ZXMsIHNjYWxlZCBieSBwcmVjaXNpb24NCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gZ2VuX2NvbW1vbl9nYXJkZW4sIA0KICAgICAgICAgICAgICAgICAgICAgIHkgPSBsblJSLCANCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMS9zcXJ0KHZhcl9sblJSKSwgDQogICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwgDQogICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNywgDQogICAgICAgICAgICAgICAgICBzdHJva2UgPSAxLA0KICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjA1KSkgKyANCiAgICAgZ2VvbV9yaWJib24oZGF0YSA9IGVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4sICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IGdlbl9jb21tb25fZ2FyZGVuLA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICBhbHBoYSA9IC41KSArIA0KICAgICBnZW9tX2xpbmUoZGF0YSA9IGVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4sICMgUHJlZGljdGVkIHJlZ3Jlc3Npb24gbGluZQ0KICAgICAgICAgICAgICAgYWVzKHkgPSBlbW1lYW4sDQogICAgICAgICAgICAgICAgICAgeCA9IGdlbl9jb21tb25fZ2FyZGVuLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArICANCiAgICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXMsIA0KICAgICAgICAgICAgICBhZXMoeCA9IEluZiwgDQogICAgICAgICAgICAgICAgICB5ID0gaWZlbHNlKHdhcm1fY29sZCA9PSAiV2FybSIsIC0wLjksIC0xLjMpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBmYWNldF93cmFwKH4gdHJhaXRfdHlwZSwgbmNvbCA9IDEpICsgICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJOdW1iZXIgb2YgZ2VuZXJhdGlvbnMgb2YgY29tbW9uIGdhcmRlbiIsIHkgPSAibG5SUiIsIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCA4KSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNSwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIyKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTEuNSwgMS41KSwNCiAgICAgICAgICAgICAgICAgICAgeGxpbSA9IGMoMCwgMTIpKQ0KDQpnZ3NhdmUoZmlsZSA9ICJmaWcvbG5SUl9nZW5fY29tbW9uX2dhcmRlbi5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA3LCBkcGkgPSA1MDApDQpgYGANCg0KIyMjICoqUG9wdWxhdGlvbiBzaXplKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5SUiB+IDAgKyB0cmFpdF90eXBlOndhcm1fY29sZCArIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOmFzc2F5X3RlbXBfZGlmZiArIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOnNjYWxlKHBvcF9zaXplKSArICMgU2VwYXJhdGUgZWZmZWN0cyBieSB0cmFpdCB0eXBlDQogICAgICAgICAgICAgICAgKHRyYWl0X3R5cGUtMXxyZWYpICsgIyBDb3JyZWxhdGlvbiBiZXR3ZWVuIHRyYWl0cyBhbW9uZyBzdHVkaWVzDQogICAgICAgICAgICAgICAgKDF8c3BlY2llcykgKyAjIFNwZWNpZXMtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfGdyKHBoeWxvZ2VueSwgY292ID0gcGh5bG9fbWF0cml4KSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5SUikpICMgVmFyaWFuY2UgY292YXJpYW5jZSBtYXRpeCBvZiBjb3JyZWxhdGVkIHNhbXBsaW5nIHZhcmlhbmNlcw0KDQojIERlZmluZSBwcmlvcnMNCnByaW9yID0gYygNCiAgcHJpb3IoY29uc3RhbnQoMSksIGNsYXNzID0gInNpZ21hIikNCikgIyBCZWNhdXNlIHRoZSByZXNpZHVhbCB2YXJpYW5jZS1jb3ZhcmlhbmNlIHN0cnVjdHVyZSBpcyBzcGVjaWZpZWQgaW4gZmNvciwgdGhlcmUgaXMgbm8gbmVlZCB0byBlc3RpbWF0ZSBzaWdtYSBzbyBpdCBpcyBsZWZ0IGFzIGEgY29uc3RhbnQNCg0KIyBGaXQgbW9kZWwNCmxuUlJfbW9kZWxfcG9wX3NpemUgPC0gYnJtKGZvcm11bGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBnYXVzc2lhbigpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEyID0gbGlzdChwaHlsb19tYXRyaXggPSBwaHlsb19tYXRyaXgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWQ1ZfbG5SUiA9IFZDVl9sblJSKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IgPSBwcmlvciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyID0gNDAwMCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm11cCA9IDIwMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYWlucyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JlcyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gMTIzKSANCiMgU2F2ZSBtb2RlbA0Kc2F2ZVJEUyhsblJSX21vZGVsX3BvcF9zaXplLCBmaWxlID0gIlJEYXRhL2xuUlJfbW9kZWxfcG9wX3NpemUucmRzIikNCmBgYA0KDQojIyMjICpNb2RlbCBvdXRwdXQqDQpgYGB7cn0NCiMgTG9hZCBtb2RlbA0KbG5SUl9tb2RlbF9wb3Bfc2l6ZSA8LSByZWFkUkRTKCJSRGF0YS9sblJSX21vZGVsX3BvcF9zaXplLnJkcyIpDQoNCiMgRGlzcGxheSBtb2RlbCBvdXRwdXQgDQpzdW1tYXJ5KGxuUlJfbW9kZWxfcG9wX3NpemUpDQoNCiMgQ2xlYW5lZCBtb2RlbCBvdXRwdXQNCmFzLmRhdGEuZnJhbWUoZml4ZWYobG5SUl9tb2RlbF9wb3Bfc2l6ZSwgc3VtbWFyeSA9IFRSVUUpKSAlPiUNCiAgIyBSZW5hbWUgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGZvciBjbGVhbmVyIGRpc3BsYXkNCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJQYXJhbWV0ZXIiKSAlPiUNCiAgbXV0YXRlKA0KICAgICMgU2ltcGxpZnkgYHRyYWl0X3R5cGVgIGFuZCBgd2FybV9jb2xkYCBpbnRlcmFjdGlvbnMNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspOndhcm1fY29sZChjb2xkfHdhcm0pIiwgIlxcMShcXDIpIiwgUGFyYW1ldGVyKSwNCiAgICAjIEFkanVzdCBmb3IgYXNzYXlfdGVtcF9kaWZmDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKVxcKChjb2xkfHdhcm0pXFwpOmFzc2F5X3RlbXBfZGlmZiIsICJcXDEoXFwyKTogYXNzYXlfdGVtcF9kaWZmIiwgUGFyYW1ldGVyKSwNCiAgICAjIFJlbW92ZSAic2NhbGUiIGZyb20gcG9wX3NpemUNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJzY2FsZXBvcF9zaXplIiwgInBvcF9zaXplIiwgUGFyYW1ldGVyKQ0KICApICU+JQ0KICAjIFJvdW5kIG51bWJlcnMgdG8gMyBkZWNpbWFsIHBvaW50cw0KICBtdXRhdGUoYWNyb3NzKGMoRXN0aW1hdGUsIFEyLjUsIFE5Ny41KSwgfiByb3VuZCguLCAzKSkpICU+JQ0KICBzZWxlY3QoUGFyYW1ldGVyLCBFc3RpbWF0ZSwgYExvd2VyIENJYCA9IFEyLjUsIGBVcHBlciBDSWAgPSBROTcuNSkgJT4lDQogIGthYmxlKCkgJT4lDQogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBwb3NpdGlvbiA9ICJjZW50ZXIiLCBmaXhlZF90aGVhZCA9IFRSVUUpICU+JQ0KICBjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSwgYm9yZGVyX3JpZ2h0ID0gVFJVRSkgJT4lDQogIHJvd19zcGVjKDAsIGJhY2tncm91bmQgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIsIGJvbGQgPSBUUlVFKSAlPiUNCiAga2FibGVfc3R5bGluZyhmaXhlZF90aGVhZCA9IFRSVUUpDQpgYGANCg0KIyMjIyAqRGF0YSB2aXN1YWxpc2F0aW9uKg0KYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0PTEwfQ0KDQojIEdlbmVyYXRlIHByZWRpY3Rpb25zDQplbW1lYW5zX3BvcF9zaXplIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5SUl9tb2RlbF9wb3Bfc2l6ZSwNCiAgc3BlY3MgPSB+IHBvcF9zaXplIHwgdHJhaXRfdHlwZSAqIHdhcm1fY29sZCwNCiAgYXQgPSBsaXN0KHBvcF9zaXplID0gc2VxKG1pbihkYXRhJHBvcF9zaXplLCBuYS5ybT1UKSwgbWF4KGRhdGEkcG9wX3NpemUsIG5hLnJtPVQpLCBieSA9IDUwKSwNCiAgICAgICAgICAgIGFzc2F5X3RlbXBfZGlmZiA9IDApKQ0KICApICMgQ29uZGl0aW9uYWwgZWZmZWN0cyBvbiBhc3NheV90ZW1wX2RpZmYgPSAwDQoNCg0KIyBDYWxjdWxhdGUgcmFuZ2Ugb2YgdmFsdWVzIGZvciBlYWNoIGNhdGVnb3J5DQpyYW5nZV9kZiA8LSBkYXRhICU+JQ0KICBncm91cF9ieSh0cmFpdF90eXBlLCB3YXJtX2NvbGQpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWluX3BvcF9zaXplID0gbWluKHBvcF9zaXplLCBuYS5ybT1UKSwNCiAgICBtYXhfcG9wX3NpemUgPSBtYXgocG9wX3NpemUsIG5hLnJtPVQpDQogICkNCg0KZW1tZWFuc19wb3Bfc2l6ZSR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX3BvcF9zaXplJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfcG9wX3NpemUkd2FybV9jb2xkIDwtIGZhY3RvcihlbW1lYW5zX3BvcF9zaXplJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgVGFpbG9yIHByZWRpY3Rpb25zIHRvIHRoZSByYW5nZSBvZiB0aGUgZGF0YQ0KZW1tZWFuc19wb3Bfc2l6ZSA8LSBlbW1lYW5zX3BvcF9zaXplICU+JQ0KICBsZWZ0X2pvaW4ocmFuZ2VfZGYsIGJ5ID0gYygidHJhaXRfdHlwZSIsICJ3YXJtX2NvbGQiKSkgJT4lDQogIGZpbHRlcigNCiAgICBwb3Bfc2l6ZSA+PSBtaW5fcG9wX3NpemUsDQogICAgcG9wX3NpemUgPD0gbWF4X3BvcF9zaXplDQogICkNCg0KIyBDYWxjdWxhdGUgc2FtcGxlIHNpemVzIGFuZCBzdHVkeSBjb3VudHMgZm9yIHBvcHVsYXRpb24gc2l6ZQ0Kc2FtcGxlX3NpemVzX3BvcF9zaXplIDwtIGRhdGEgJT4lDQogIGZpbHRlcihpcy5uYShwb3Bfc2l6ZSk9PUZBTFNFKSAlPiUgDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBlc3RpbWF0ZXMgPSBuKCksDQogICAgc3R1ZGllcyA9IG5fZGlzdGluY3QocmVmKQ0KICApDQoNCiMgUGxvdA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsICAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBwb3Bfc2l6ZSwgDQogICAgICAgICAgICAgICAgICAgICAgeSA9IGxuUlIsIA0KICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxL3NxcnQodmFyX2xuUlIpLCANCiAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgICBzaGFwZSA9IDIxLCANCiAgICAgICAgICAgICAgICAgIGFscGhhID0gMC43LCANCiAgICAgICAgICAgICAgICAgIHN0cm9rZSA9IDEsDQogICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IDAuMDUpKSArIA0KICAgICBnZW9tX3JpYmJvbihkYXRhID0gZW1tZWFuc19wb3Bfc2l6ZSwgIyBTaGFkZWQgYXJlYSBmb3IgY3JlZGlibGUgaW50ZXJ2YWxzDQogICAgICAgICAgICAgICAgIGFlcyh4ID0gcG9wX3NpemUsDQogICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgIGFscGhhID0gLjUpICsgDQogICAgIGdlb21fbGluZShkYXRhID0gZW1tZWFuc19wb3Bfc2l6ZSwgIyBQcmVkaWN0ZWQgcmVncmVzc2lvbiBsaW5lDQogICAgICAgICAgICAgICBhZXMoeSA9IGVtbWVhbiwNCiAgICAgICAgICAgICAgICAgICB4ID0gcG9wX3NpemUsDQogICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsgIA0KICAgICBnZW9tX3RleHQoZGF0YSA9IHNhbXBsZV9zaXplc19wb3Bfc2l6ZSwgDQogICAgICAgICAgICAgIGFlcyh4ID0gSW5mLCANCiAgICAgICAgICAgICAgICAgIHkgPSBpZmVsc2Uod2FybV9jb2xkID09ICJXYXJtIiwgLTAuOSwgLTEuMyksICAjIFNhbXBsZSBzaXplcw0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEuMDUsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGZhY2V0X3dyYXAofiB0cmFpdF90eXBlLCBuY29sID0gMSkgKyAgIyBEaWZmZXJlbnQgcGFuZWxzIGZvciBlYWNoIHRyYWl0DQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgbGFicyh4ID0gIlBvcHVsYXRpb24gc2l6ZSIsIHkgPSAibG5SUiIsIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCA4KSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNSwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIyKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTEuNSwgMS41KSkNCg0KZ2dzYXZlKGZpbGUgPSAiZmlnL2xuUlJfcG9wX3NpemUucG5nIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNywgZHBpID0gNTAwKQ0KYGBgDQoNCg0KIyMjICoqQWxsIG1vZGVyYXRvcnMqKiANCg0KIyMjIyAqTW9kZWwgc3BlY2lmaWNhdGlvbioNCmBgYHtyLCBldmFsID0gRn0NCiMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KZm9ybXVsYSA8LSBiZihsblJSIH4gMCArIHRyYWl0X3R5cGU6d2FybV9jb2xkICsgDQogICAgICAgICAgICAgICAgdHJhaXRfdHlwZTp3YXJtX2NvbGQ6YXNzYXlfdGVtcF9kaWZmICsgDQogICAgICAgICAgICAgICAgdHJhaXRfdHlwZTp3YXJtX2NvbGQ6c2NhbGUoc2VsZWN0X3RlbXBfZGlmZikgKw0KICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOnNjYWxlKGdlbl9zZWxlY3Rpb24pICsgDQogICAgICAgICAgICAgICAgdHJhaXRfdHlwZTp3YXJtX2NvbGQ6c2NhbGUoZ2VuX2NvbW1vbl9nYXJkZW4pICsgIyBTZXBhcmF0ZSBlZmZlY3RzIGJ5IHRyYWl0IHR5cGUNCiAgICAgICAgICAgICAgICAodHJhaXRfdHlwZS0xfHJlZikgKyAjIENvcnJlbGF0aW9uIGJldHdlZW4gdHJhaXRzIGFtb25nIHN0dWRpZXMNCiAgICAgICAgICAgICAgICAoMXxzcGVjaWVzKSArICMgU3BlY2llcy1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8Z3IocGh5bG9nZW55LCBjb3YgPSBwaHlsb19tYXRyaXgpKSArICMgUGh5bG9nZW5ldGljIHJlbGF0ZWRuZXNzDQogICAgICAgICAgICAgICAgKDF8ZXhwZXJpbWVudF9JRCkgKyAjIEV4cGVyaW1lbnQtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfG9icykgKyAjIE9ic2VydmF0aW9uLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICBmY29yKFZDVl9sblJSKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5SUl9tb2RlbF9hbGxfbW9kZXJhdG9ycyA8LSBicm0oZm9ybXVsYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gZ2F1c3NpYW4oKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTIgPSBsaXN0KHBoeWxvX21hdHJpeCA9IHBoeWxvX21hdHJpeCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVkNWX2xuUlIgPSBWQ1ZfbG5SUiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IgPSBwcmlvciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDQwMDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm11cCA9IDIwMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhaW5zID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gMTIzKSANCg0KIyBTYXZlIG1vZGVsDQpzYXZlUkRTKGxuUlJfbW9kZWxfYWxsX21vZGVyYXRvcnMsIGZpbGUgPSAiUkRhdGEvbG5SUl9tb2RlbF9hbGxfbW9kZXJhdG9ycy5yZHMiKQ0KYGBgDQoNCiMjIyMgKk1vZGVsIG91dHB1dCoNCmBgYHtyfQ0KIyBMb2FkIG1vZGVsDQpsblJSX21vZGVsX2FsbF9tb2RlcmF0b3JzIDwtIHJlYWRSRFMoIlJEYXRhL2xuUlJfbW9kZWxfYWxsX21vZGVyYXRvcnMucmRzIikNCg0KIyBEaXNwbGF5IG1vZGVsIG91dHB1dCANCnN1bW1hcnkobG5SUl9tb2RlbF9hbGxfbW9kZXJhdG9ycykNCg0KIyBDbGVhbmVkIG1vZGVsIG91dHB1dA0KYXMuZGF0YS5mcmFtZShmaXhlZihsblJSX21vZGVsX2FsbF9tb2RlcmF0b3JzLCBzdW1tYXJ5ID0gVFJVRSkpICU+JQ0KICAjIFJlbmFtZSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgZm9yIGNsZWFuZXIgZGlzcGxheQ0KICByb3duYW1lc190b19jb2x1bW4odmFyID0gIlBhcmFtZXRlciIpICU+JQ0KICBtdXRhdGUoDQogICAgIyBTaW1wbGlmeSBgdHJhaXRfdHlwZWAgYW5kIGB3YXJtX2NvbGRgIGludGVyYWN0aW9ucw0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKyk6d2FybV9jb2xkKGNvbGR8d2FybSkiLCAiXFwxKFxcMikiLCBQYXJhbWV0ZXIpLA0KICAgICMgQWRqdXN0IGZvciBhc3NheV90ZW1wX2RpZmYNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspXFwoKGNvbGR8d2FybSlcXCk6YXNzYXlfdGVtcF9kaWZmIiwgIlxcMShcXDIpOiBhc3NheV90ZW1wX2RpZmYiLCBQYXJhbWV0ZXIpLA0KICAgICMgUmVtb3ZlICJzY2FsZSIgZnJvbSBhbGwgbW9kZXJhdG9yIHZhcmlhYmxlcw0KICAgIFBhcmFtZXRlciA9IGdzdWIoInNjYWxlIiwgIiIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KIA0KIyBHZW5lcmF0ZSBwcmVkaWN0ZWQgdmFsdWVzIGF0IGRpZmZlcmVudCBhc3NheSB0ZW1wZXJhdHVyZXMNCmVtbWVhbnNfZnVsbF9tb2RlbCA8LSBhcy5kYXRhLmZyYW1lKGVtbWVhbnMoDQogIGxuUlJfbW9kZWxfYWxsX21vZGVyYXRvcnMsDQogIHNwZWNzID0gfiBhc3NheV90ZW1wX2RpZmYgKiBzZWxlY3RfdGVtcF9kaWZmICogZ2VuX3NlbGVjdGlvbiAqIGdlbl9jb21tb25fZ2FyZGVuIHwgdHJhaXRfdHlwZSAqIHdhcm1fY29sZCwNCiAgYXQgPSBsaXN0KGFzc2F5X3RlbXBfZGlmZiA9IGMoLTguNSwgLTQsIDAsIDQsIDUsIC01LCAxNywgMjApKSAjIFByZWRpY3QgYXQgdW5pcXVlIG1pbiwgY29udHJvbCwgbWF4IHZhbHVlcw0KKSkNCg0KIyBDYWxjdWxhdGUgcmFuZ2Ugb2YgdmFsdWVzIGZvciBlYWNoIGNhdGVnb3J5DQpyYW5nZV9kZiA8LSBkYXRhICU+JQ0KICBncm91cF9ieSh0cmFpdF90eXBlLCB3YXJtX2NvbGQpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWluX2Fzc2F5ID0gbWluKGFzc2F5X3RlbXBfZGlmZiksDQogICAgbWF4X2Fzc2F5ID0gbWF4KGFzc2F5X3RlbXBfZGlmZiksDQogICAgY29udHJvbF9hc3NheSA9IDANCiAgKQ0KDQplbW1lYW5zX2Z1bGxfbW9kZWwkdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19mdWxsX21vZGVsJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfZnVsbF9tb2RlbCR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfZnVsbF9tb2RlbCR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KDQojIFRhaWxvciBwcmVkaWN0aW9ucyB0byB0aGUgcmFuZ2Ugb2YgdGhlIGRhdGENCmVtbWVhbnNfZnVsbF9tb2RlbCAlPiUNCiAgbGVmdF9qb2luKHJhbmdlX2RmLCBieSA9IGMoInRyYWl0X3R5cGUiLCAid2FybV9jb2xkIikpICU+JQ0KICBmaWx0ZXIoDQogICAgYXNzYXlfdGVtcF9kaWZmID09IG1pbl9hc3NheSB8DQogICAgYXNzYXlfdGVtcF9kaWZmID09IG1heF9hc3NheSB8DQogICAgYXNzYXlfdGVtcF9kaWZmID09IGNvbnRyb2xfYXNzYXkpICU+JSANCiAgICBkcGx5cjo6c2VsZWN0KC1taW5fYXNzYXksIC1tYXhfYXNzYXksIC1jb250cm9sX2Fzc2F5KSAlPiUgDQogICAgbXV0YXRlKHBlcmNlbnRhZ2VfY2hhbmdlID0gKGV4cChlbW1lYW4pIC0gMSkgKiAxMDAsDQogICAgICAgICAgIHBlcmNlbnRhZ2VfbG93ZXJfSFBEID0gKGV4cChsb3dlci5IUEQpIC0gMSkgKiAxMDAsDQogICAgICAgICAgIHBlcmNlbnRhZ2VfdXBwZXJfSFBEID0gKGV4cCh1cHBlci5IUEQpIC0gMSkgKiAxMDApICU+JQ0KICBtdXRhdGUoYWNyb3NzKGMoZW1tZWFuLCANCiAgICAgICAgICAgICAgICAgIGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgcGVyY2VudGFnZV9jaGFuZ2UsDQogICAgICAgICAgICAgICAgICBwZXJjZW50YWdlX2xvd2VyX0hQRCwgDQogICAgICAgICAgICAgICAgICBwZXJjZW50YWdlX3VwcGVyX0hQRCksIH4gcm91bmQoLiwgMykpKSAlPiUgICAjIFJvdW5kIG51bWJlcnMgdG8gMyBkZWNpbWFsIHBvaW50cw0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkRhdGEgdmlzdWFsaXNhdGlvbioNCg0KKipNYXJnaW5hbCBtZWFucyoqIA0KYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0PTEwfQ0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucyBhdCBhc3NheV90ZW1wX2RpZmYgPSAwLCBvciA1IGRlZ3JlZXMgYmVsb3cgb3IgYWJvdmUgdGhlIGNvbnRyb2wgdGVtcGVyYXR1cmVzDQplbW1lYW5zX2Z1bGxfbW9kZWwgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsblJSX21vZGVsX2FsbF9tb2RlcmF0b3JzLA0KICBzcGVjcyA9IH4gYXNzYXlfdGVtcF9kaWZmICogc2VsZWN0X3RlbXBfZGlmZiAqIGdlbl9zZWxlY3Rpb24gKiBnZW5fY29tbW9uX2dhcmRlbiB8IHRyYWl0X3R5cGUgKiB3YXJtX2NvbGQsDQogIGF0ID0gbGlzdChhc3NheV90ZW1wX2RpZmYgPSBjKC01LCAwLCA1KSAjIFJlLWFjY2xpbWF0ZWQgdG8gY29udHJvbCwgb3IgNSBkZWdyZWVzIGFib3ZlL2JlbG93IHRoZSBjb250cm9sDQogICkpKSANCg0KIyBSZW5hbWUgdmFyaWFibGUgbGV2ZWxzDQplbW1lYW5zX2Z1bGxfbW9kZWwkdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19mdWxsX21vZGVsJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfZnVsbF9tb2RlbCR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfZnVsbF9tb2RlbCR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KZW1tZWFuc19mdWxsX21vZGVsDQoNCiMgUGxvdA0KZ2dwbG90KCkgKw0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUsIA0KICAgICAgICAgICAgICAgbHdkPTEpICsNCiAgICBnZW9tX3F1YXNpcmFuZG9tKGRhdGEgPSBkYXRhLCAgICAgIyBQbG90IGVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGxuUlIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5SUikpLCANCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsDQogICAgICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMywgDQogICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuMykgKw0KICAgIGdlb21fZXJyb3JiYXIoZGF0YSA9IGZpbHRlcihlbW1lYW5zX2Z1bGxfbW9kZWwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2F5X3RlbXBfZGlmZiA9PSAiLTUiKSwgICMgNSBkZWdyZWVzIGJlbG93IGNvbnRyb2wgKGJhY2tncm91bmQpDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBEKSwgDQogICAgICAgICAgICAgICAgICBjb2xvcj0id2hpdGUiLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIuNzUsDQogICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMTYsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9LTAuMjUpKSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gZmlsdGVyKGVtbWVhbnNfZnVsbF9tb2RlbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID09ICItNSIpLCAgIyA1IGRlZ3JlZXMgYmVsb3cgY29udHJvbCAoYmFja2dyb3VuZCkNCiAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTp3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgIHkgPSBlbW1lYW4pLA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgIHNpemUgPSA0LjUsIA0KICAgICAgICAgICAgICAgc3Ryb2tlID0gMiwNCiAgICAgICAgICAgICAgIGNvbG9yPSJ3aGl0ZSIsDQogICAgICAgICAgICAgICBmaWxsID0gIndoaXRlIiwNCiAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fbnVkZ2UoeD0tMC4yNSkpICsNCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBmaWx0ZXIoZW1tZWFuc19mdWxsX21vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPT0gIi01IiksICMgNSBkZWdyZWVzIGJlbG93IGNvbnRyb2wgKGNyZWRpYmxlIGludGVydmFscykNCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTp3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQpLCANCiAgICAgICAgICAgICAgICAgIGNvbG9yPSIjMDZCNEJBIiwNCiAgICAgICAgICAgICAgICAgIHNpemUgPSAyLA0KICAgICAgICAgICAgICAgICAgd2lkdGggPSAwLjEyLA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4PS0wLjI1KSkgKw0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGZpbHRlcihlbW1lYW5zX2Z1bGxfbW9kZWwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2F5X3RlbXBfZGlmZiA9PSAiLTUiKSwgIyA1IGRlZ3JlZXMgYmVsb3cgY29udHJvbCAgKHBvaW50IGVzdGltYXRlcykNCiAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTp3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgIHkgPSBlbW1lYW4pLA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgIHNpemUgPSAzLjUsIA0KICAgICAgICAgICAgICAgc3Ryb2tlID0gMiwNCiAgICAgICAgICAgICAgIGNvbG9yPSIjMDZCNEJBIiwNCiAgICAgICAgICAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4PS0wLjI1KSkgKw0KDQogICAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBmaWx0ZXIoZW1tZWFuc19mdWxsX21vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPT0gIjAiKSwgICMgY29udHJvbCB0ZW1wZXJhdHVyZSAoYmFja2dyb3VuZCkNCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTp3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQpLCANCiAgICAgICAgICAgICAgICAgIGNvbG9yPSJ3aGl0ZSIsDQogICAgICAgICAgICAgICAgICBzaXplID0gMi43NSwNCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4xNiwNCiAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fbnVkZ2UoeD0wKSkgKw0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGZpbHRlcihlbW1lYW5zX2Z1bGxfbW9kZWwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2F5X3RlbXBfZGlmZiA9PSAiMCIpLCAgIyBjb250cm9sIHRlbXBlcmF0dXJlIChiYWNrZ3JvdW5kKQ0KICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgeSA9IGVtbWVhbiksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIyLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDQuNSwgDQogICAgICAgICAgICAgICBzdHJva2UgPSAyLA0KICAgICAgICAgICAgICAgY29sb3I9IndoaXRlIiwNCiAgICAgICAgICAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4PTApKSArDQogICAgZ2VvbV9lcnJvcmJhcihkYXRhID0gZmlsdGVyKGVtbWVhbnNfZnVsbF9tb2RlbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID09ICIwIiksICMgY29udHJvbCB0ZW1wZXJhdHVyZSAoY3JlZGlibGUgaW50ZXJ2YWxzKQ0KICAgICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCksIA0KICAgICAgICAgICAgICAgICAgY29sb3I9ImJsYWNrIiwNCiAgICAgICAgICAgICAgICAgIHNpemUgPSAyLA0KICAgICAgICAgICAgICAgICAgd2lkdGggPSAwLjEyLA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4PTApKSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gZmlsdGVyKGVtbWVhbnNfZnVsbF9tb2RlbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID09ICIwIiksICMgY29udHJvbCB0ZW1wZXJhdHVyZSAocG9pbnQgZXN0aW1hdGVzKQ0KICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgeSA9IGVtbWVhbiksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIyLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDMuNSwgDQogICAgICAgICAgICAgICBzdHJva2UgPSAyLA0KICAgICAgICAgICAgICAgY29sb3I9ImJsYWNrIiwNCiAgICAgICAgICAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4PTApKSArDQogIA0KICAgICAgZ2VvbV9lcnJvcmJhcihkYXRhID0gZmlsdGVyKGVtbWVhbnNfZnVsbF9tb2RlbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID09ICI1IiksICAjIDUgZGVncmVlcyBhYm92ZSBjb250cm9sIChiYWNrZ3JvdW5kKQ0KICAgICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCksIA0KICAgICAgICAgICAgICAgICAgY29sb3I9IndoaXRlIiwNCiAgICAgICAgICAgICAgICAgIHNpemUgPSAyLjc1LA0KICAgICAgICAgICAgICAgICAgd2lkdGggPSAwLjE2LA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4PTAuMjUpKSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gZmlsdGVyKGVtbWVhbnNfZnVsbF9tb2RlbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID09ICI1IiksICAjIDUgZGVncmVlcyBhYm92ZSBjb250cm9sIChiYWNrZ3JvdW5kKQ0KICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgeSA9IGVtbWVhbiksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIzLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDQuNSwgDQogICAgICAgICAgICAgICBzdHJva2UgPSAyLA0KICAgICAgICAgICAgICAgY29sb3I9IndoaXRlIiwNCiAgICAgICAgICAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4PTAuMjUpKSArDQogICAgZ2VvbV9lcnJvcmJhcihkYXRhID0gZmlsdGVyKGVtbWVhbnNfZnVsbF9tb2RlbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID09ICI1IiksICMgNSBkZWdyZWVzIGFib3ZlIGNvbnRyb2wgKGNyZWRpYmxlIGludGVydmFscykNCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTp3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQpLCANCiAgICAgICAgICAgICAgICAgIGNvbG9yPSIjRTgwNzU2IiwNCiAgICAgICAgICAgICAgICAgIHNpemUgPSAyLA0KICAgICAgICAgICAgICAgICAgd2lkdGggPSAwLjEyLA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4PTAuMjUpKSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gZmlsdGVyKGVtbWVhbnNfZnVsbF9tb2RlbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID09ICI1IiksICMgNSBkZWdyZWVzIGFib3ZlIGNvbnRyb2wgKHBvaW50IGVzdGltYXRlcykNCiAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTp3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgIHkgPSBlbW1lYW4pLA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMywNCiAgICAgICAgICAgICAgIHNpemUgPSAzLjUsIA0KICAgICAgICAgICAgICAgc3Ryb2tlID0gMiwNCiAgICAgICAgICAgICAgIGNvbG9yPSIjRTgwNzU2IiwNCiAgICAgICAgICAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4PTAuMjUpKSArDQogIA0KICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzLCAgIyBTYW1wbGUgc2l6ZSBhbm5vdGF0aW9ucyANCiAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICB5ID0gMS41LA0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIA0KICAgIHRoZW1lX2J3KCkgKyAgICAgIyBDdXN0b21pemUgdGhlIHBsb3QNCiAgICBsYWJzKHkgPSAibG5SUiIsIHggPSAiIikgKw0KICAgIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgOCkpKyANCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiLCAiIzA2QjRCQSIsICIjRTgwNzU2IiwgIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiQ29sZCIgPSAiIzA2QjRCQSIsICJXYXJtIiA9ICIjRTgwNzU2IikpICsgICMgVGV4dCBjb2xvdXINCiAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTQpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuNSkpICsNCiAgICBndWlkZXMoZmlsbCA9ICJub25lIiwgc2l6ZSA9ICJub25lIikrDQogICAgY29vcmRfZmxpcCgpICsgDQogICAgeWxpbSgtMS41LCAxLjUpDQoNCmdnc2F2ZShmaWxlID0gImZpZy9sblJSX2FsbF9tb2RlcmF0b3JzX21hcmdpbmFsX21lYW5zLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDgsIGRwaSA9IDUwMCkNCmBgYA0KDQoqKk92ZXJhbGwgdHJlbmQgd2l0aCBhc3NheSB0ZW1wZXJhdHVyZSoqIA0KYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0PTEwfQ0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucyBmb3IgYWxsIGFzc2F5IHRlbXBlcmF0dXJlcw0KZW1tZWFuc19mdWxsX21vZGVsX2Fzc2F5IDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5SUl9tb2RlbF9hbGxfbW9kZXJhdG9ycywNCiAgc3BlY3MgPSB+IGFzc2F5X3RlbXBfZGlmZiAqIHNlbGVjdF90ZW1wX2RpZmYgKiBnZW5fc2VsZWN0aW9uICogZ2VuX2NvbW1vbl9nYXJkZW4gfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3QoYXNzYXlfdGVtcF9kaWZmID0gc2VxKG1pbihkYXRhJGFzc2F5X3RlbXBfZGlmZiksIG1heChkYXRhJGFzc2F5X3RlbXBfZGlmZiksIGJ5ID0gMC41KSAjIFJlLWFjY2xpbWF0ZWQgdG8gY29udHJvbCwgb3IgNSBkZWdyZWVzIGFib3ZlL2JlbG93IHRoZSBjb250b2wNCiAgKSkpIA0KDQojIENhbGN1bGF0ZSByYW5nZSBvZiB2YWx1ZXMgZm9yIGVhY2ggY2F0ZWdvcnkNCnJhbmdlX2RmIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtaW5fYXNzYXlfdGVtcF9kaWZmID0gbWluKGFzc2F5X3RlbXBfZGlmZiksDQogICAgbWF4X2Fzc2F5X3RlbXBfZGlmZiA9IG1heChhc3NheV90ZW1wX2RpZmYpDQogICkNCg0KIyBSZW5hbWUgdmFyaWFibGUgbGV2ZWxzDQplbW1lYW5zX2Z1bGxfbW9kZWxfYXNzYXkkdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19mdWxsX21vZGVsX2Fzc2F5JHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfZnVsbF9tb2RlbF9hc3NheSR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfZnVsbF9tb2RlbF9hc3NheSR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KDQojIFRhaWxvciBwcmVkaWN0aW9ucyB0byB0aGUgcmFuZ2Ugb2YgdGhlIGRhdGENCmVtbWVhbnNfZnVsbF9tb2RlbF9hc3NheSA8LSBlbW1lYW5zX2Z1bGxfbW9kZWxfYXNzYXkgJT4lDQogIGxlZnRfam9pbihyYW5nZV9kZiwgYnkgPSBjKCJ0cmFpdF90eXBlIiwgIndhcm1fY29sZCIpKSAlPiUNCiAgZmlsdGVyKA0KICAgIGFzc2F5X3RlbXBfZGlmZiA+PSBtaW5fYXNzYXlfdGVtcF9kaWZmLA0KICAgIGFzc2F5X3RlbXBfZGlmZiA8PSBtYXhfYXNzYXlfdGVtcF9kaWZmDQogICkNCg0KDQojIFBsb3QNCmdncGxvdCgpICsgDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgIyBIb3Jpem9udGFsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSkgKyAgDQogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgIyBWZXJ0aWNhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUpICsgDQogICAgZ2VvbV9wb2ludChkYXRhID0gZGF0YSwgIyBFZmZlY3Qgc2l6ZXMsIHNjYWxlZCBieSBwcmVjaXNpb24NCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gYXNzYXlfdGVtcF9kaWZmLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5SUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5SUiksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX2Z1bGxfbW9kZWxfYXNzYXksICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IGFzc2F5X3RlbXBfZGlmZiwNCiAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICBmaWxsID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgYWxwaGEgPSAuNSkgKyANCiAgICAgZ2VvbV9saW5lKGRhdGEgPSBlbW1lYW5zX2Z1bGxfbW9kZWxfYXNzYXksICAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSBhc3NheV90ZW1wX2RpZmYsDQogICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsgDQogIA0KICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzLCANCiAgICAgICAgICAgICAgYWVzKHggPSBJbmYsIA0KICAgICAgICAgICAgICAgICAgeSA9IGlmZWxzZSh3YXJtX2NvbGQgPT0gIldhcm0iLCAtMiwgLTIuNzUpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICANCiAgZmFjZXRfd3JhcCh+IHRyYWl0X3R5cGUsIG5jb2wgPSAxKSArICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJBc3NheSB0ZW1wZXJhdHVyZSBkaWZmZXJlbmNlIiwgeSA9ICJsblJSIiwNCiAgICAgICBjb2wgPSAiUmVnaW1lIikgKw0KICB0aGVtZV9idygpICsgDQogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgOCkpKyANCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjUsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxOCksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAyMikpICsNCiAgICBndWlkZXMoZmlsbCA9ICJub25lIiwgc2l6ZSA9ICJub25lIikrDQogICAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0zLCAzKSkNCg0KZ2dzYXZlKGZpbGUgPSAiZmlnL2xuUlJfYWxsX21vZGVyYXRvcnNfYXNzYXlfdGVtcF9kaWZmLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDEwLCBkcGkgPSA1MDApDQpgYGANCg0KDQojIyAqKkNoYW5nZXMgaW4gcmVsYXRpdmUgdHJhaXQgdmFyaWFuY2UgKGxuQ1ZSKSoqIHsudGFic2V0IC50YWJzZXRfZmFkZSAudGFic2V0X3BpbGxzfQ0KDQojIyMgKipPdmVyYWxsIG1vZGVsKioNCg0KIyMjIyAqTW9kZWwgc3BlY2lmaWNhdGlvbioNCmBgYHtyLCBldmFsID0gRn0NCiMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KZm9ybXVsYSA8LSBiZihsbkNWUiB+IHRyYWl0X3R5cGUgLTEgKyAjIFNlcGFyYXRlIGVmZmVjdHMgYnkgdHJhaXQgdHlwZQ0KICAgICAgICAgICAgICAgICh0cmFpdF90eXBlLTF8cmVmKSArICMgQ29ycmVsYXRpb24gYmV0d2VlbiB0cmFpdHMgYW1vbmcgc3R1ZGllcw0KICAgICAgICAgICAgICAgICgxfHNwZWNpZXMpICsgIyBTcGVjaWVzLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxncihwaHlsb2dlbnksIGNvdiA9IHBoeWxvX21hdHJpeCkpICsgIyBQaHlsb2dlbmV0aWMgcmVsYXRlZG5lc3MNCiAgICAgICAgICAgICAgICAoMXxleHBlcmltZW50X0lEKSArICMgRXhwZXJpbWVudC1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8b2JzKSArICMgT2JzZXJ2YXRpb24tbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgIGZjb3IoVkNWX2xuQ1ZSKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5DVlJfbW9kZWxfb3ZlcmFsbCA8LSBicm0oZm9ybXVsYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBnYXVzc2lhbigpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTIgPSBsaXN0KHBoeWxvX21hdHJpeCA9IHBoeWxvX21hdHJpeCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWQ1ZfbG5DVlIgPSBWQ1ZfbG5DVlIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IgPSBwcmlvciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OSwgbWF4X3RyZWVkZXB0aCA9IDE1KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXIgPSA0MDAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm11cCA9IDIwMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFpbnMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gMTIzKSANCg0KIyBTYXZlIG1vZGVsDQpzYXZlUkRTKGxuQ1ZSX21vZGVsX292ZXJhbGwsIGZpbGUgPSAiUkRhdGEvbG5DVlJfbW9kZWxfb3ZlcmFsbC5yZHMiKQ0KYGBgDQoNCiMjIyMgKk1vZGVsIG91dHB1dCoNCmBgYHtyfQ0KIyBMb2FkIG1vZGVsDQpsbkNWUl9tb2RlbF9vdmVyYWxsIDwtIHJlYWRSRFMoIlJEYXRhL2xuQ1ZSX21vZGVsX292ZXJhbGwucmRzIikNCg0KIyBEaXNwbGF5IG1vZGVsIG91dHB1dCANCnN1bW1hcnkobG5DVlJfbW9kZWxfb3ZlcmFsbCkNCg0KIyBDbGVhbmVkIG1vZGVsIG91dHB1dA0KYXMuZGF0YS5mcmFtZShmaXhlZihsbkNWUl9tb2RlbF9vdmVyYWxsLCBzdW1tYXJ5ID0gVFJVRSkpICU+JQ0KICAjIFJlbmFtZSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgZm9yIGNsZWFuZXIgZGlzcGxheQ0KICByb3duYW1lc190b19jb2x1bW4odmFyID0gIlBhcmFtZXRlciIpICU+JSANCiAgbXV0YXRlKA0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKykiLCAiXFwxIiwgUGFyYW1ldGVyKQ0KICApICU+JQ0KICAjIFJvdW5kIG51bWJlcnMgdG8gMyBkZWNpbWFsIHBvaW50cw0KICBtdXRhdGUoYWNyb3NzKGMoRXN0aW1hdGUsIFEyLjUsIFE5Ny41KSwgfiByb3VuZCguLCAzKSkpICU+JQ0KICBzZWxlY3QoUGFyYW1ldGVyLCBFc3RpbWF0ZSwgYExvd2VyIENJYCA9IFEyLjUsIGBVcHBlciBDSWAgPSBROTcuNSkgJT4lDQogIGthYmxlKCkgJT4lDQogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBwb3NpdGlvbiA9ICJjZW50ZXIiLCBmaXhlZF90aGVhZCA9IFRSVUUpICU+JQ0KICBjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSwgYm9yZGVyX3JpZ2h0ID0gVFJVRSkgJT4lDQogIHJvd19zcGVjKDAsIGJhY2tncm91bmQgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIsIGJvbGQgPSBUUlVFKSAlPiUNCiAga2FibGVfc3R5bGluZyhmaXhlZF90aGVhZCA9IFRSVUUpDQpgYGANCg0KDQojIyMjICpIZXRlcm9nZW5laXR5IGFuYWx5c2lzKg0KYGBge3J9DQojIEV4dHJhY3RpbmcgdGhlIHBvc3RlcmlvciBkaXN0cmlidXRpb24gZnJvbSB0aGUgbW9kZWwNCnBvc3RlcmlvciA8LSBwb3N0ZXJpb3Jfc2FtcGxlcyhsbkNWUl9tb2RlbF9vdmVyYWxsKQ0KDQojIENhbGN1bGF0ZSBtZWFzdXJlbWVudCBlcnJvciB2YXJpYW5jZQ0Kc2lnbWEyX3YgPC0gc3VtKDEvZGlhZyhWQ1ZfbG5DVlIpKSAqIChsZW5ndGgoZGlhZyhWQ1ZfbG5DVlIpKS0gMSkvKHN1bSgxL2RpYWcoVkNWX2xuQ1ZSKSleMiAtIHN1bSgoMS9kaWFnKFZDVl9sbkNWUikpXjIpKQ0KDQojIENhbGN1bGF0ZSB0aGUgdG90YWwgdmFyaWFuY2UgKGluY2x1ZGluZyB0aGUgbWVhc3VyZW1lbnQgZXJyb3IgdmFyaWFuY2UpDQp2YXJfdG90YWwgPC0gcG9zdGVyaW9yJHNkX2V4cGVyaW1lbnRfSURfX0ludGVyY2VwdCArDQogICAgICAgICAgICAgcG9zdGVyaW9yJHNkX29ic19fSW50ZXJjZXB0ICsNCiAgICAgICAgICAgICBwb3N0ZXJpb3Ikc2RfcGh5bG9nZW55X19JbnRlcmNlcHQgKw0KICAgICAgICAgICAgIHBvc3RlcmlvciRzZF9yZWZfX3RyYWl0X3R5cGVib2R5X3NpemUgKw0KICAgICAgICAgICAgIHBvc3RlcmlvciRzZF9yZWZfX3RyYWl0X3R5cGVmZWN1bmRpdHkgKw0KICAgICAgICAgICAgIHBvc3RlcmlvciRzZF9yZWZfX3RyYWl0X3R5cGVzdXJ2aXZhbCArDQogICAgICAgICAgICAgcG9zdGVyaW9yJHNkX3NwZWNpZXNfX0ludGVyY2VwdCArDQogICAgICAgICAgICAgc2lnbWEyX3YNCg0KIyBDYWxjdWxhdGUgaGV0ZXJvZ2VuZWl0eSAoSTIpDQpJMiA8LSBsaXN0KA0KICAgIEkyX3RvdGFsID0gKHZhcl90b3RhbCAtIHNpZ21hMl92KSAvIHZhcl90b3RhbCwgIyBUb3RhbCBoZXRlcm9nZW5laXR5DQogICAgSTJfc3R1ZHkgPSAocG9zdGVyaW9yJHNkX3JlZl9fdHJhaXRfdHlwZWJvZHlfc2l6ZSArICMgSGV0ZXJvZ2VuZWl0eSBleHBsYWluZWQgYnkgc3R1ZHkgZGlmZmVyZW5jZXMNCiAgICAgICAgICAgICAgICBwb3N0ZXJpb3Ikc2RfcmVmX190cmFpdF90eXBlZmVjdW5kaXR5ICsNCiAgICAgICAgICAgICAgICBwb3N0ZXJpb3Ikc2RfcmVmX190cmFpdF90eXBlc3Vydml2YWwpIC8gdmFyX3RvdGFsLA0KICAgIEkyX2V4cCA9IHBvc3RlcmlvciRzZF9leHBlcmltZW50X0lEX19JbnRlcmNlcHQgLyB2YXJfdG90YWwsICMgSGV0ZXJvZ2VuZWl0eSBleHBsYWluZWQgYnkgZXhwZXJpbWVudCBkaWZmZXJlbmNlcw0KICAgIEkyX3NwID0gcG9zdGVyaW9yJHNkX3NwZWNpZXNfX0ludGVyY2VwdCAvIHZhcl90b3RhbCwgIyBIZXRlcm9nZW5laXR5IGV4cGxhaW5lZCBieSBzcGVjaWVzIGRpZmZlcmVuY2VzDQogICAgSTJfcGh5bG8gPSBwb3N0ZXJpb3Ikc2RfcGh5bG9nZW55X19JbnRlcmNlcHQgLyB2YXJfdG90YWwsICMgSGV0ZXJvZ2VuZWl0eSBleHBsYWluZWQgYnkgcGh5bG9nZW5ldGljIHJlbGF0ZWRuZXNzDQogICAgSTJfb2JzID0gcG9zdGVyaW9yJHNkX29ic19fSW50ZXJjZXB0IC8gdmFyX3RvdGFsICMgSGV0ZXJvZ2VuZWl0eSBleHBsYWluZWQgYnkgcmVzaWR1YWwgdmFyaWF0aW9uDQoNCikNCg0KIyBDYWxjdWxhdGUgbWVhbiBhbmQgY3JlZGlibGUgaW50ZXJ2YWxzIA0Kc3VtbWFyeV90YWJsZSA8LSB0KHNhcHBseShJMiwgZnVuY3Rpb24oeCkgew0KICAgIGMoTWVhbiA9IDEwMCpyb3VuZChtZWFuKHgpLDQpLCANCiAgICAgIGAgYCA9IDEwMCogcm91bmQocXVhbnRpbGUoeCwgMC4wMjUpLDQpLCANCiAgICAgIGAgYCA9IDEwMCpyb3VuZChxdWFudGlsZSh4LCAwLjk3NSksNCkpDQp9KSkNCg0KIyBDdXN0b21pc2UgdGFibGUNCnN1bW1hcnlfdGFibGUgPC0gc3VtbWFyeV90YWJsZSAlPiUNCiAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KICAgIHJvd25hbWVzX3RvX2NvbHVtbigiVmFyaWFibGUiKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICAgIFZhcmlhYmxlID0gcmVjb2RlKFZhcmlhYmxlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiSTJfdG90YWwiICA9ICJUb3RhbCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJJMl9zdHVkeSIgID0gIlN0dWR5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkkyX2V4cCIgICAgPSAiRXhwZXJpbWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJJMl9zcCIgICAgID0gIlNwZWNpZXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiSTJfcGh5bG8iICA9ICJQaHlsb2dlbnkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiSTJfb2JzIiAgICA9ICJSZXNpZHVhbCIpDQogICAgKSAlPiUNCiAgICByZW5hbWUoDQogICAgICAgIGxvd2VyX0hQRCA9IGAgLjIuNSVgLA0KICAgICAgICB1cHBlcl9IUEQgPSBgIC45Ny41JWANCiAgICApICU+JQ0KICBtdXRhdGUoDQogICAgVmFyaWFibGUgPSBwYXN0ZTAoIkk8c3VwPjI8L3N1cD48c3ViPiIsIFZhcmlhYmxlKSAgICMgQ3JlYXRlIGEgbmV3IGNvbHVtbiB3aXRoIGZvcm1hdHRlZCBJwrIgYW5kIHN1YnNjcmlwdHMNCiAgKQ0KDQoNCiMgRGlzcGxheSB0YWJsZQ0Ka2FibGUoc3VtbWFyeV90YWJsZSwgImh0bWwiLCBlc2NhcGUgPSBGQUxTRSwgDQogICAgICBjb2wubmFtZXMgPSBjKCJIZXRlcm9nZW5laXR5ICglKSIsICJNZWFuIiwgIkxvd2VyIEhQRCIsICJVcHBlciBIUEQiKSwNCiAgICAgIGFsaWduID0gYygnbCcsICdyJywgJ3InLCAncicpKSAlPiUNCiAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImNlbnRlciIsIGZpeGVkX3RoZWFkID0gVFJVRSkgJT4lDQogIGNvbHVtbl9zcGVjKDEsIHdpZHRoID0gIjIwMHB4IiwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkRhdGEgdmlzdWFsaXNhdGlvbioNCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD03fQ0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucw0KZW1tZWFuc19vdmVyYWxsIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucyhsbkNWUl9tb2RlbF9vdmVyYWxsLCB+IHRyYWl0X3R5cGUpKQ0KDQplbW1lYW5zX292ZXJhbGwkdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19vdmVyYWxsJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQojIFBsb3QNCmdncGxvdCgpICsNCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1LCANCiAgICAgICAgICAgICAgIGx3ZD0xKSArDQogICAgZ2VvbV9xdWFzaXJhbmRvbShkYXRhID0gZGF0YSwgIyBQbG90IGVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5DVlIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxL3NxcnQodmFyX2xuQ1ZSKSksIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9ICJncmF5NzUiLA0KICAgICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4yNSwgDQogICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuMikgKw0KICAgIGdlb21fZXJyb3JiYXIoZGF0YSA9IGVtbWVhbnNfb3ZlcmFsbCwgICAjIFBsb3QgdGhlIHBvaW50IGVzdGltYXRlcyBpbiB3aGl0ZSBmb3IgYmFja2dyb3VuZA0KICAgICAgICAgICAgICAgICAgYWVzKHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsDQogICAgICAgICAgICAgICAgICAgICAgeCA9IHRyYWl0X3R5cGUpLCANCiAgICAgICAgICAgICAgICAgIHNpemUgPSAyLA0KICAgICAgICAgICAgICAgICAgd2lkdGggPSAwLjA4NSwNCiAgICAgICAgICAgICAgICAgIGNvbG9yID0gIndoaXRlIikgKw0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGVtbWVhbnNfb3ZlcmFsbCwgIyBQbG90IHRoZSBjcmVkaWJsZSBpbnRlcnZhbHMgaW4gd2hpdGUgZm9yIGJhY2tncm91bmQNCiAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgeSA9IGVtbWVhbiksDQogICAgICAgICAgICAgICBzaXplID0gNC41LCANCiAgICAgICAgICAgICAgIHN0cm9rZSA9IDEuNSwNCiAgICAgICAgICAgICAgIHNoYXBlID0gMjEsDQogICAgICAgICAgICAgICBjb2xvcj0id2hpdGUiLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJ3aGl0ZSIpICsNCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBlbW1lYW5zX292ZXJhbGwsICAjIFBsb3QgdGhlIHBvaW50IGVzdGltYXRlcyANCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCksIA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSwNCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4wNzUsDQogICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsNCiAgICBnZW9tX3BvaW50KGRhdGEgPSBlbW1lYW5zX292ZXJhbGwsICMgUGxvdCB0aGUgY3JlZGlibGUgaW50ZXJ2YWxzDQogICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgIHkgPSBlbW1lYW4pLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDQsDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLA0KICAgICAgICAgICAgICAgc3Ryb2tlID0gMS41LA0KICAgICAgICAgICAgICAgY29sb3I9ImJsYWNrIiwNCiAgICAgICAgICAgICAgIGZpbGwgPSAid2hpdGUiKSArDQogICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXNfdHJhaXRzLCAgIyBTYW1wbGUgc2l6ZSBhbm5vdGF0aW9ucyANCiAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgIHkgPSAzLA0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIikpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICAgIHRoZW1lX2J3KCkgKyAgICAgIyBDdXN0b21pemUgdGhlIHBsb3QNCiAgICBsYWJzKHkgPSAibG5DVlIiLCB4ID0gIiIpICsNCiAgICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDIsIDgpKSsgDQogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpKSArDQogICAgZ3VpZGVzKGNvbG9yID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICBjb29yZF9mbGlwKCkgKyANCiAgICB5bGltKC0zLCAzKQ0KDQojIFNhdmUgZmlndXJlDQpnZ3NhdmUoZmlsZSA9ICJmaWcvbG5DVlJfb3ZlcmFsbC5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA3LCBkcGkgPSA1MDApDQpgYGANCg0KIyMjICoqVGVtcGVyYXR1cmUgcmVnaW1lKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5DVlIgfiB0cmFpdF90eXBlOndhcm1fY29sZCAtMSArICMgU2VwYXJhdGUgZWZmZWN0cyBieSB0cmFpdCB0eXBlDQogICAgICAgICAgICAgICAgKHRyYWl0X3R5cGUtMXxyZWYpICsgIyBDb3JyZWxhdGlvbiBiZXR3ZWVuIHRyYWl0cyBhbW9uZyBzdHVkaWVzDQogICAgICAgICAgICAgICAgKDF8c3BlY2llcykgKyAjIFNwZWNpZXMtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfGdyKHBoeWxvZ2VueSwgY292ID0gcGh5bG9fbWF0cml4KSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5DVlIpKSAjIFZhcmlhbmNlIGNvdmFyaWFuY2UgbWF0aXggb2YgY29ycmVsYXRlZCBzYW1wbGluZyB2YXJpYW5jZXMNCg0KIyBEZWZpbmUgcHJpb3JzDQpwcmlvciA9IGMoDQogIHByaW9yKGNvbnN0YW50KDEpLCBjbGFzcyA9ICJzaWdtYSIpDQopICMgQmVjYXVzZSB0aGUgcmVzaWR1YWwgdmFyaWFuY2UtY292YXJpYW5jZSBzdHJ1Y3R1cmUgaXMgc3BlY2lmaWVkIGluIGZjb3IsIHRoZXJlIGlzIG5vIG5lZWQgdG8gZXN0aW1hdGUgc2lnbWEgc28gaXQgaXMgbGVmdCBhcyBhIGNvbnN0YW50DQoNCiMgRml0IG1vZGVsDQpsbkNWUl9tb2RlbF93YXJtX2NvbGQgPC0gYnJtKGZvcm11bGEsIA0KICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gZ2F1c3NpYW4oKSwNCiAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLCANCiAgICAgICAgICAgICAgICAgIGRhdGEyID0gbGlzdChwaHlsb19tYXRyaXggPSBwaHlsb19tYXRyaXgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVkNWX2xuQ1ZSID0gVkNWX2xuQ1ZSKSwNCiAgICAgICAgICAgICAgICAgIHByaW9yID0gcHJpb3IsDQogICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxNSksDQogICAgICAgICAgICAgICAgICBpdGVyID0gNDAwMCwgDQogICAgICAgICAgICAgICAgICB3YXJtdXAgPSAyMDAwLA0KICAgICAgICAgICAgICAgICAgY2hhaW5zID0gNCwgDQogICAgICAgICAgICAgICAgICBjb3JlcyA9IDQsIA0KICAgICAgICAgICAgICAgICAgc2VlZCA9IDEyMykgDQoNCiMgU2F2ZSBtb2RlbA0Kc2F2ZVJEUyhsbkNWUl9tb2RlbF93YXJtX2NvbGQsIGZpbGUgPSAiUkRhdGEvbG5DVlJfbW9kZWxfd2FybV9jb2xkLnJkcyIpDQpgYGANCg0KIyMjIyAqTW9kZWwgb3V0cHV0Kg0KYGBge3J9DQojIExvYWQgbW9kZWwNCmxuQ1ZSX21vZGVsX3dhcm1fY29sZCA8LSByZWFkUkRTKCJSRGF0YS9sbkNWUl9tb2RlbF93YXJtX2NvbGQucmRzIikNCg0KIyBEaXNwbGF5IG1vZGVsIG91dHB1dCANCnN1bW1hcnkobG5DVlJfbW9kZWxfd2FybV9jb2xkKQ0KDQojIENsZWFuZWQgbW9kZWwgb3V0cHV0DQphcy5kYXRhLmZyYW1lKGZpeGVmKGxuQ1ZSX21vZGVsX3dhcm1fY29sZCwgc3VtbWFyeSA9IFRSVUUpKSAlPiUNCiAgIyBSZW5hbWUgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGZvciBjbGVhbmVyIGRpc3BsYXkNCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJQYXJhbWV0ZXIiKSAlPiUgDQogIG11dGF0ZSgNCiAgICAjIFNpbXBsaWZ5IGB0cmFpdF90eXBlYCBhbmQgYHdhcm1fY29sZGAgaW50ZXJhY3Rpb25zDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKTp3YXJtX2NvbGQoY29sZHx3YXJtKSIsICJcXDEoXFwyKSIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkNvbnRyYXN0cyogDQpgYGB7cn0NCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbXMgPC0gZW1tZWFucyhsbkNWUl9tb2RlbF93YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgIHNwZWNzID0gfiB3YXJtX2NvbGQgfCB0cmFpdF90eXBlKQ0KDQojIEdlbmVyYXRlIGNvbnRyYXN0cw0KY29udHJhc3QoZW1tcywgbWV0aG9kID0gInBhaXJ3aXNlIikNCmBgYA0KDQojIyMjICpEYXRhIHZpc3VhbGlzYXRpb24qDQpgYGB7ciwgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQ9N30NCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbWVhbnNfd2FybV9jb2xkIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucyhsbkNWUl9tb2RlbF93YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwZWNzID0gfiB3YXJtX2NvbGQgfCB0cmFpdF90eXBlKSkNCg0KZW1tZWFuc193YXJtX2NvbGQkdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc193YXJtX2NvbGQkdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KDQplbW1lYW5zX3dhcm1fY29sZCR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfd2FybV9jb2xkJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQojIFBsb3QNCmdncGxvdCgpICsNCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1LCANCiAgICAgICAgICAgICAgIGx3ZD0xKSArDQogICAgZ2VvbV9xdWFzaXJhbmRvbShkYXRhID0gZGF0YSwgICAgICMgUGxvdCBlZmZlY3Qgc2l6ZXMsIHNjYWxlZCBieSBwcmVjaXNpb24NCiAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTp3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBsbkNWUiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMS9zcXJ0KHZhcl9sbkNWUikpLCANCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsDQogICAgICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMjUsIA0KICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjMpICsNCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBlbW1lYW5zX3dhcm1fY29sZCwgICMgUGxvdCB0aGUgcG9pbnQgZXN0aW1hdGVzIGluIHdoaXRlIGZvciBiYWNrZ3JvdW5kDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBEKSwgDQogICAgICAgICAgICAgICAgICBjb2xvcj0id2hpdGUiLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIuNSwNCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4xNykgKw0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGVtbWVhbnNfd2FybV9jb2xkLCAgIyBQbG90IHRoZSBjcmVkaWJsZSBpbnRlcnZhbHMgaW4gd2hpdGUgZm9yIGJhY2tncm91bmQNCiAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTp3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgIHkgPSBlbW1lYW4pLA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgIHNpemUgPSA0LCANCiAgICAgICAgICAgICAgIHN0cm9rZSA9IDIsDQogICAgICAgICAgICAgICBjb2xvcj0id2hpdGUiLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJ3aGl0ZSIpICsNCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBlbW1lYW5zX3dhcm1fY29sZCwgIyBQbG90IHRoZSBwb2ludCBlc3RpbWF0ZXMgDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBEKSwgDQogICAgICAgICAgICAgICAgICBjb2xvcj0iYmxhY2siLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIsDQogICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMTUpICsNCiAgICBnZW9tX3BvaW50KGRhdGEgPSBlbW1lYW5zX3dhcm1fY29sZCwgIyBQbG90IHRoZSBjcmVkaWJsZSBpbnRlcnZhbHMNCiAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTp3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgIHkgPSBlbW1lYW4pLA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgIHNpemUgPSAzLjUsIA0KICAgICAgICAgICAgICAgc3Ryb2tlID0gMiwNCiAgICAgICAgICAgICAgIGNvbG9yPSJibGFjayIsDQogICAgICAgICAgICAgICBmaWxsID0gIndoaXRlIikgKw0KICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzLCAgIyBTYW1wbGUgc2l6ZSBhbm5vdGF0aW9ucyANCiAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICB5ID0gMywNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICAgIHRoZW1lX2J3KCkgKyAgICAgIyBDdXN0b21pemUgdGhlIHBsb3QNCiAgICBsYWJzKHkgPSAibG5DVlIiLCB4ID0gIiIpICsNCiAgICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDIsIDgpKSsgDQojICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNBNUY4MjAiLCAiIzczQjcwNiIsICAiIzlDRUZGQyIsICIjMDZBMkJBIiwgICIjRkVEMkVEIiwgIiNCOTA2NzQiKSkrDQogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IiwgIiMwNkI0QkEiLCAiI0U4MDc1NiIsICIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpKSArDQogICAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIHNpemUgPSAibm9uZSIpKw0KICAgIGNvb3JkX2ZsaXAoKSArIA0KICAgIHlsaW0oLTMsIDMpDQoNCmdnc2F2ZShmaWxlID0gImZpZy9sbkNWUl93YXJtX2NvbGQucG5nIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNywgZHBpID0gNTAwKQ0KYGBgDQoNCiMjIyAqKkFzc2F5IHRlbXBlcmF0dXJlIGRpZmZlcmVuY2UqKiANCg0KV2UgY2FsY3VsYXRlZCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBhc3NheSB0ZW1wZXJhdHVyZSBhbmQgY29udHJvbCB0ZW1wZXJhdHVyZSAoYXNzYXlfdGVtcF9kaWZmKSB0byBhY2NvdW50IGZvciB0aGUgZmFjdCB0aGF0IGFuaW1hbHMgd2VyZSB0ZXN0ZWQgdG8gYSBkaWZmZXJlbnQgcmFuZ2Ugb2YgdGVtcGVyYXR1cmVzLiBXZSBhbHNvIHByZWRpY3RlZCB0aGF0IGVmZmVjdHMgd2lsbCB2YXJ5IGlmIHRyYWl0cyBhcmUgYXNzYXllZCBhdCBjb2xkZXItIG9yIHdhcm1lci10aGFuLWNvbnRyb2wgY29uZGl0aW9ucywgZGVwZW5kaW5nIG9uIHRoZSB0ZW1wZXJhdHVyZSByZWdpbWUuIA0KQmVjYXVzZSB0aGUgdmFyaWF0aW9uIGluIGFzc2F5IHRlbXBlcmF0dXJlIGdlbmVyYXRlcyBzb21lIG51aXNhbmNlIGhldGVyb2dlbmVpdHkgKHNlbnN1IE5vYmxlIGV0IGFsLiwgMjAxNyksIHRoZSByZXN1bHRzIG9mIHN1YnNlcXVlbnQgbW9kZWxzIHdlcmUgcHJvdmlkZWQgYWZ0ZXIgY29udHJvbGxpbmcgZm9yIGFzc2F5IHRlbXBlcmF0dXJlIGRpZmZlcmVuY2VzLiBJbiBvcmRlciB3b3JkcywgdGhlIHJlc3VsdHMgb2YgYWxsIG1vZGVyYXRvcnMgYXJlIGNvbmRpdGlvbmFsIG9uIGFzc2F5IHRlbXBlcmF0dXJlLCBtZWFuaW5nIHRoYXQgcmVzdWx0cyBhcmUgaW50ZXJwcmV0YWJsZSBhcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGNvbnRyb2wgYW5kIHNlbGVjdGVkIGxpbmVzLCB3aGVuIGFuaW1hbHMgYXJlIHRlc3RlZCBhdCB0aGUgY29udHJvbCB0ZW1wZXJhdHVyZS4gDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5DVlIgfiAwICsgdHJhaXRfdHlwZTp3YXJtX2NvbGQgKyB0cmFpdF90eXBlOndhcm1fY29sZDphc3NheV90ZW1wX2RpZmYgKyAjIFNlcGFyYXRlIGVmZmVjdHMgYnkgdHJhaXQgdHlwZQ0KICAgICAgICAgICAgICAgICh0cmFpdF90eXBlLTF8cmVmKSArICMgQ29ycmVsYXRpb24gYmV0d2VlbiB0cmFpdHMgYW1vbmcgc3R1ZGllcw0KICAgICAgICAgICAgICAgICgxfHNwZWNpZXMpICsgIyBTcGVjaWVzLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxncihwaHlsb2dlbnksIGNvdiA9IHBoeWxvX21hdHJpeCkpICsgIyBQaHlsb2dlbmV0aWMgcmVsYXRlZG5lc3MNCiAgICAgICAgICAgICAgICAoMXxleHBlcmltZW50X0lEKSArICMgRXhwZXJpbWVudC1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8b2JzKSArICMgT2JzZXJ2YXRpb24tbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgIGZjb3IoVkNWX2xuQ1ZSKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5DVlJfbW9kZWxfYXNzYXlfdGVtcF9kaWZmIDwtIGJybShmb3JtdWxhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBnYXVzc2lhbigpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhMiA9IGxpc3QocGh5bG9fbWF0cml4ID0gcGh5bG9fbWF0cml4LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWQ1ZfbG5DVlIgPSBWQ1ZfbG5DVlIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yID0gcHJpb3IsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXIgPSA0MDAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXJtdXAgPSAyMDAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYWlucyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEyMykgDQoNCiMgU2F2ZSBtb2RlbA0Kc2F2ZVJEUyhsbkNWUl9tb2RlbF9hc3NheV90ZW1wX2RpZmYsIGZpbGUgPSAiUkRhdGEvbG5DVlJfbW9kZWxfYXNzYXlfdGVtcF9kaWZmLnJkcyIpDQpgYGANCg0KIyMjIyAqTW9kZWwgb3V0cHV0Kg0KYGBge3J9DQojIExvYWQgbW9kZWwNCmxuQ1ZSX21vZGVsX2Fzc2F5X3RlbXBfZGlmZiA8LSByZWFkUkRTKCJSRGF0YS9sbkNWUl9tb2RlbF9hc3NheV90ZW1wX2RpZmYucmRzIikNCg0KIyBEaXNwbGF5IG1vZGVsIG91dHB1dCANCnN1bW1hcnkobG5DVlJfbW9kZWxfYXNzYXlfdGVtcF9kaWZmKQ0KDQojIENsZWFuZWQgbW9kZWwgb3V0cHV0DQphcy5kYXRhLmZyYW1lKGZpeGVmKGxuQ1ZSX21vZGVsX2Fzc2F5X3RlbXBfZGlmZiwgc3VtbWFyeSA9IFRSVUUpKSAlPiUNCiAgIyBSZW5hbWUgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGZvciBjbGVhbmVyIGRpc3BsYXkNCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJQYXJhbWV0ZXIiKSAlPiUgDQogIG11dGF0ZSgNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspOndhcm1fY29sZChjb2xkfHdhcm0pIiwgIlxcMShcXDIpIiwgUGFyYW1ldGVyKSwNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspXFwod2FybVxcKTphc3NheV90ZW1wX2RpZmYiLCAiXFwxKHdhcm0pOiBhc3NheV90ZW1wX2RpZmYiLCBQYXJhbWV0ZXIpDQogICkgJT4lDQogICMgUm91bmQgbnVtYmVycyB0byAzIGRlY2ltYWwgcG9pbnRzDQogIG11dGF0ZShhY3Jvc3MoYyhFc3RpbWF0ZSwgUTIuNSwgUTk3LjUpLCB+IHJvdW5kKC4sIDMpKSkgJT4lDQogIHNlbGVjdChQYXJhbWV0ZXIsIEVzdGltYXRlLCBgTG93ZXIgQ0lgID0gUTIuNSwgYFVwcGVyIENJYCA9IFE5Ny41KSAlPiUNCiAga2FibGUoKSAlPiUNCiAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImNlbnRlciIsIGZpeGVkX3RoZWFkID0gVFJVRSkgJT4lDQogIGNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFLCBib3JkZXJfcmlnaHQgPSBUUlVFKSAlPiUNCiAgcm93X3NwZWMoMCwgYmFja2dyb3VuZCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIiwgYm9sZCA9IFRSVUUpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZpeGVkX3RoZWFkID0gVFJVRSkNCmBgYA0KDQojIyMjICpEYXRhIHZpc3VhbGlzYXRpb24qDQoNCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD0xMH0NCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbWVhbnNfYXNzYXlfdGVtcF9kaWZmIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5DVlJfbW9kZWxfYXNzYXlfdGVtcF9kaWZmLA0KICBzcGVjcyA9IH4gYXNzYXlfdGVtcF9kaWZmIHwgdHJhaXRfdHlwZSAqIHdhcm1fY29sZCwNCiAgYXQgPSBsaXN0KGFzc2F5X3RlbXBfZGlmZiA9IHNlcShtaW4oZGF0YSRhc3NheV90ZW1wX2RpZmYpLCBtYXgoZGF0YSRhc3NheV90ZW1wX2RpZmYpLCBieSA9IDAuNSkpKQ0KICApDQoNCiMgQ2FsY3VsYXRlIHJhbmdlIG9mIHZhbHVlcyBmb3IgZWFjaCBjYXRlZ29yeQ0KcmFuZ2VfZGYgPC0gZGF0YSAlPiUNCiAgZ3JvdXBfYnkodHJhaXRfdHlwZSwgd2FybV9jb2xkKSAlPiUNCiAgc3VtbWFyaXplKA0KICAgIG1pbl9hc3NheV90ZW1wX2RpZmYgPSBtaW4oYXNzYXlfdGVtcF9kaWZmKSwNCiAgICBtYXhfYXNzYXlfdGVtcF9kaWZmID0gbWF4KGFzc2F5X3RlbXBfZGlmZikNCiAgKQ0KDQplbW1lYW5zX2Fzc2F5X3RlbXBfZGlmZiR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX2Fzc2F5X3RlbXBfZGlmZiR0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYm9keV9zaXplIiwgImZlY3VuZGl0eSIsICJzdXJ2aXZhbCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQm9keSBzaXplIiwgIkZlY3VuZGl0eSIsICJTdXJ2aXZhbCIpKQ0KDQplbW1lYW5zX2Fzc2F5X3RlbXBfZGlmZiR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfYXNzYXlfdGVtcF9kaWZmJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgVGFpbG9yIHByZWRpY3Rpb25zIHRvIHRoZSByYW5nZSBvZiB0aGUgZGF0YQ0KZW1tZWFuc19hc3NheV90ZW1wX2RpZmYgPC0gZW1tZWFuc19hc3NheV90ZW1wX2RpZmYgJT4lDQogIGxlZnRfam9pbihyYW5nZV9kZiwgYnkgPSBjKCJ0cmFpdF90eXBlIiwgIndhcm1fY29sZCIpKSAlPiUNCiAgZmlsdGVyKA0KICAgIGFzc2F5X3RlbXBfZGlmZiA+PSBtaW5fYXNzYXlfdGVtcF9kaWZmLA0KICAgIGFzc2F5X3RlbXBfZGlmZiA8PSBtYXhfYXNzYXlfdGVtcF9kaWZmDQogICkNCg0KIyBQbG90DQpnZ3Bsb3QoKSArIA0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUpICsgIA0KICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsICMgVmVydGljYWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsICMgRWZmZWN0IHNpemVzLCBzY2FsZWQgYnkgcHJlY2lzaW9uDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IGFzc2F5X3RlbXBfZGlmZiwgDQogICAgICAgICAgICAgICAgICAgICAgeSA9IGxuQ1ZSLCANCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMS9zcXJ0KHZhcl9sbkNWUiksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX2Fzc2F5X3RlbXBfZGlmZiwgIyBTaGFkZWQgYXJlYSBmb3IgY3JlZGlibGUgaW50ZXJ2YWxzDQogICAgICAgICAgICAgICAgIGFlcyh4ID0gYXNzYXlfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICBhbHBoYSA9IC41KSArIA0KICAgICBnZW9tX2xpbmUoZGF0YSA9IGVtbWVhbnNfYXNzYXlfdGVtcF9kaWZmLCAgIyBQcmVkaWN0ZWQgcmVncmVzc2lvbiBsaW5lDQogICAgICAgICAgICAgICBhZXMoeSA9IGVtbWVhbiwNCiAgICAgICAgICAgICAgICAgICB4ID0gYXNzYXlfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArIA0KICANCiAgICBnZW9tX3RleHQoZGF0YSA9IHNhbXBsZV9zaXplcywgDQogICAgICAgICAgICAgIGFlcyh4ID0gSW5mLCANCiAgICAgICAgICAgICAgICAgIHkgPSBpZmVsc2Uod2FybV9jb2xkID09ICJXYXJtIiwgLTIsIC0yLjc1KSwgICMgU2FtcGxlIHNpemVzDQogICAgICAgICAgICAgICAgICBsYWJlbCA9IHBhc3RlMCgiayA9ICIsIGVzdGltYXRlcywgIiAoIiwgc3R1ZGllcywgIikiKSwNCiAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgIGhqdXN0ID0gMS4wNSwgc2l6ZSA9IDUsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgDQogIGZhY2V0X3dyYXAofiB0cmFpdF90eXBlLCBuY29sID0gMSkgKyAjIERpZmZlcmVudCBwYW5lbHMgZm9yIGVhY2ggdHJhaXQNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICBsYWJzKHggPSAiQXNzYXkgdGVtcGVyYXR1cmUgZGlmZmVyZW5jZSIsIHkgPSAibG5DVlIiLA0KICAgICAgIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCA4KSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNSwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIyKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTMsIDMpKQ0KDQpnZ3NhdmUoZmlsZSA9ICJmaWcvbG5DVlJfYXNzYXlfdGVtcF9kaWZmLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDEwLCBkcGkgPSA1MDApDQpgYGANCg0KDQojIyMgKipTZWxlY3Rpb24gdGVtcGVyYXR1cmUqKiANCg0KIyMjIyAqTW9kZWwgc3BlY2lmaWNhdGlvbioNCmBgYHtyLCBldmFsID0gRn0NCiMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KZm9ybXVsYSA8LSBiZihsbkNWUiB+IDAgKyB0cmFpdF90eXBlOndhcm1fY29sZCArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFpdF90eXBlOndhcm1fY29sZDphc3NheV90ZW1wX2RpZmYgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhaXRfdHlwZTp3YXJtX2NvbGQ6c2VsZWN0X3RlbXBfZGlmZiArICMgU2VwYXJhdGUgZWZmZWN0cyBieSB0cmFpdCB0eXBlDQogICAgICAgICAgICAgICAgKHRyYWl0X3R5cGUtMXxyZWYpICsgIyBDb3JyZWxhdGlvbiBiZXR3ZWVuIHRyYWl0cyBhbW9uZyBzdHVkaWVzDQogICAgICAgICAgICAgICAgKDF8c3BlY2llcykgKyAjIFNwZWNpZXMtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfGdyKHBoeWxvZ2VueSwgY292ID0gcGh5bG9fbWF0cml4KSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5DVlIpKSAjIFZhcmlhbmNlIGNvdmFyaWFuY2UgbWF0aXggb2YgY29ycmVsYXRlZCBzYW1wbGluZyB2YXJpYW5jZXMNCg0KIyBEZWZpbmUgcHJpb3JzDQpwcmlvciA9IGMoDQogIHByaW9yKGNvbnN0YW50KDEpLCBjbGFzcyA9ICJzaWdtYSIpDQopICMgQmVjYXVzZSB0aGUgcmVzaWR1YWwgdmFyaWFuY2UtY292YXJpYW5jZSBzdHJ1Y3R1cmUgaXMgc3BlY2lmaWVkIGluIGZjb3IsIHRoZXJlIGlzIG5vIG5lZWQgdG8gZXN0aW1hdGUgc2lnbWEgc28gaXQgaXMgbGVmdCBhcyBhIGNvbnN0YW50DQoNCiMgRml0IG1vZGVsDQpsbkNWUl9tb2RlbF9zZWxfdGVtcF9kaWZmIDwtIGJybShmb3JtdWxhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gZ2F1c3NpYW4oKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhMiA9IGxpc3QocGh5bG9fbWF0cml4ID0gcGh5bG9fbWF0cml4LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVkNWX2xuQ1ZSID0gVkNWX2xuQ1ZSKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IgPSBwcmlvciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyID0gNDAwMCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm11cCA9IDIwMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYWlucyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JlcyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gMTIzKSANCg0KIyBTYXZlIG1vZGVsDQpzYXZlUkRTKGxuQ1ZSX21vZGVsX3NlbF90ZW1wX2RpZmYsIGZpbGUgPSAiUkRhdGEvbG5DVlJfbW9kZWxfc2VsX3RlbXBfZGlmZi5yZHMiKQ0KYGBgDQoNCiMjIyMgKk1vZGVsIG91dHB1dCoNCmBgYHtyfQ0KIyBMb2FkIG1vZGVsDQpsbkNWUl9tb2RlbF9zZWxfdGVtcF9kaWZmIDwtIHJlYWRSRFMoIlJEYXRhL2xuQ1ZSX21vZGVsX3NlbF90ZW1wX2RpZmYucmRzIikNCg0KIyBEaXNwbGF5IG1vZGVsIG91dHB1dCANCnN1bW1hcnkobG5DVlJfbW9kZWxfc2VsX3RlbXBfZGlmZikNCg0KIyBDbGVhbmVkIG1vZGVsIG91dHB1dA0KYXMuZGF0YS5mcmFtZShmaXhlZihsbkNWUl9tb2RlbF9zZWxfdGVtcF9kaWZmLCBzdW1tYXJ5ID0gVFJVRSkpICU+JQ0KICAjIFJlbmFtZSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgZm9yIGNsZWFuZXIgZGlzcGxheQ0KICByb3duYW1lc190b19jb2x1bW4odmFyID0gIlBhcmFtZXRlciIpICU+JSANCiAgbXV0YXRlKA0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKyk6d2FybV9jb2xkKGNvbGR8d2FybSkiLCAiXFwxKFxcMikiLCBQYXJhbWV0ZXIpLA0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKylcXCh3YXJtXFwpOnNlbGVjdF90ZW1wX2RpZmYiLCAiXFwxKHdhcm0pOiBzZWxlY3RfdGVtcF9kaWZmIiwgUGFyYW1ldGVyKQ0KICApICU+JQ0KICAjIFJvdW5kIG51bWJlcnMgdG8gMyBkZWNpbWFsIHBvaW50cw0KICBtdXRhdGUoYWNyb3NzKGMoRXN0aW1hdGUsIFEyLjUsIFE5Ny41KSwgfiByb3VuZCguLCAzKSkpICU+JQ0KICBzZWxlY3QoUGFyYW1ldGVyLCBFc3RpbWF0ZSwgYExvd2VyIENJYCA9IFEyLjUsIGBVcHBlciBDSWAgPSBROTcuNSkgJT4lDQogIGthYmxlKCkgJT4lDQogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBwb3NpdGlvbiA9ICJjZW50ZXIiLCBmaXhlZF90aGVhZCA9IFRSVUUpICU+JQ0KICBjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSwgYm9yZGVyX3JpZ2h0ID0gVFJVRSkgJT4lDQogIHJvd19zcGVjKDAsIGJhY2tncm91bmQgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIsIGJvbGQgPSBUUlVFKSAlPiUNCiAga2FibGVfc3R5bGluZyhmaXhlZF90aGVhZCA9IFRSVUUpDQpgYGANCg0KIyMjIyAqRGF0YSB2aXN1YWxpc2F0aW9uKg0KDQpgYGB7ciwgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQ9MTB9DQojIEdlbmVyYXRlIHByZWRpY3Rpb25zDQplbW1lYW5zX3NlbF90ZW1wX2RpZmYgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsbkNWUl9tb2RlbF9zZWxfdGVtcF9kaWZmLA0KICBzcGVjcyA9IH4gc2VsZWN0X3RlbXBfZGlmZiB8IHRyYWl0X3R5cGUgKiB3YXJtX2NvbGQsDQogIGF0ID0gbGlzdChzZWxlY3RfdGVtcF9kaWZmID0gc2VxKG1pbihkYXRhJHNlbGVjdF90ZW1wX2RpZmYpLCBtYXgoZGF0YSRzZWxlY3RfdGVtcF9kaWZmKSwgYnkgPSAwLjUpLA0KICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID0gMCkpDQogICkgIyBDb25kaXRpb25hbCBlZmZlY3RzIG9uIGFzc2F5X3RlbXBfZGlmZiA9IDANCg0KIyBDYWxjdWxhdGUgcmFuZ2Ugb2YgdmFsdWVzIGZvciBlYWNoIGNhdGVnb3J5DQpyYW5nZV9kZiA8LSBkYXRhICU+JQ0KICBncm91cF9ieSh0cmFpdF90eXBlLCB3YXJtX2NvbGQpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWluX3NlbGVjdF90ZW1wX2RpZmYgPSBtaW4oc2VsZWN0X3RlbXBfZGlmZiksDQogICAgbWF4X3NlbGVjdF90ZW1wX2RpZmYgPSBtYXgoc2VsZWN0X3RlbXBfZGlmZikNCiAgKQ0KDQplbW1lYW5zX3NlbF90ZW1wX2RpZmYkdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19zZWxfdGVtcF9kaWZmJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfc2VsX3RlbXBfZGlmZiR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfc2VsX3RlbXBfZGlmZiR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KDQojIFRhaWxvciBwcmVkaWN0aW9ucyB0byB0aGUgcmFuZ2Ugb2YgdGhlIGRhdGENCmVtbWVhbnNfc2VsX3RlbXBfZGlmZiA8LSBlbW1lYW5zX3NlbF90ZW1wX2RpZmYgJT4lDQogIGxlZnRfam9pbihyYW5nZV9kZiwgYnkgPSBjKCJ0cmFpdF90eXBlIiwgIndhcm1fY29sZCIpKSAlPiUNCiAgZmlsdGVyKA0KICAgIHNlbGVjdF90ZW1wX2RpZmYgPj0gbWluX3NlbGVjdF90ZW1wX2RpZmYsDQogICAgc2VsZWN0X3RlbXBfZGlmZiA8PSBtYXhfc2VsZWN0X3RlbXBfZGlmZg0KICApDQoNCiMgUGxvdA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsICAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBzZWxlY3RfdGVtcF9kaWZmLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5DVlIsIA0KICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxL3NxcnQodmFyX2xuQ1ZSKSwgDQogICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwgDQogICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNywgDQogICAgICAgICAgICAgICAgICBzdHJva2UgPSAxLA0KICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjA1KSkgKyANCiAgICAgZ2VvbV9yaWJib24oZGF0YSA9IGVtbWVhbnNfc2VsX3RlbXBfZGlmZiwgIyBTaGFkZWQgYXJlYSBmb3IgY3JlZGlibGUgaW50ZXJ2YWxzDQogICAgICAgICAgICAgICAgIGFlcyh4ID0gc2VsZWN0X3RlbXBfZGlmZiwNCiAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICBmaWxsID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgYWxwaGEgPSAuNSkgKyANCiAgICAgZ2VvbV9saW5lKGRhdGEgPSBlbW1lYW5zX3NlbF90ZW1wX2RpZmYsICMgUHJlZGljdGVkIHJlZ3Jlc3Npb24gbGluZQ0KICAgICAgICAgICAgICAgYWVzKHkgPSBlbW1lYW4sDQogICAgICAgICAgICAgICAgICAgeCA9IHNlbGVjdF90ZW1wX2RpZmYsDQogICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsgIA0KICAgICBnZW9tX3RleHQoZGF0YSA9IHNhbXBsZV9zaXplcywgDQogICAgICAgICAgICAgIGFlcyh4ID0gSW5mLCANCiAgICAgICAgICAgICAgICAgIHkgPSBpZmVsc2Uod2FybV9jb2xkID09ICJXYXJtIiwgLTIsIC0yLjc1KSwgICMgU2FtcGxlIHNpemVzDQogICAgICAgICAgICAgICAgICBsYWJlbCA9IHBhc3RlMCgiayA9ICIsIGVzdGltYXRlcywgIiAoIiwgc3R1ZGllcywgIikiKSwNCiAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgIGhqdXN0ID0gMS4wNSwgc2l6ZSA9IDUsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgZmFjZXRfd3JhcCh+IHRyYWl0X3R5cGUsIG5jb2wgPSAxKSArICAjIERpZmZlcmVudCBwYW5lbHMgZm9yIGVhY2ggdHJhaXQNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICBsYWJzKHggPSAiU2VsZWN0aW9uIHRlbXBlcmF0dXJlIGRpZmZlcmVuY2UiLCB5ID0gImxuQ1ZSIiwgY29sID0gIlJlZ2ltZSIpICsNCiAgdGhlbWVfYncoKSArIA0KICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDIsIDgpKSsgDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDI1LCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTgpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgICAgYXhpcy50ZXh0LnkgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwLCANCiAgICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCBoanVzdCA9IDAuNSksDQogICAgICAgICAgYXhpcy50ZXh0LnggPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuNSksDQogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMjIpKSArDQogICAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIHNpemUgPSAibm9uZSIpKw0KICAgIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygtMywgMykpDQoNCmdnc2F2ZShmaWxlID0gImZpZy9sbkNWUl9zZWxfdGVtcF9kaWZmLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIGRwaSA9IDUwMCkNCmBgYA0KDQoNCiMjIyAqKk51bWJlciBvZiBnZW5lcmF0aW9ucyBvZiBzZWxlY3Rpb24qKiANCg0KIyMjIyAqTW9kZWwgc3BlY2lmaWNhdGlvbioNCmBgYHtyLCBldmFsID0gRn0NCiMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KZm9ybXVsYSA8LSBiZihsbkNWUiB+IDAgKyB0cmFpdF90eXBlOndhcm1fY29sZCArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFpdF90eXBlOndhcm1fY29sZDphc3NheV90ZW1wX2RpZmYgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhaXRfdHlwZTp3YXJtX2NvbGQ6c2NhbGUoZ2VuX3NlbGVjdGlvbikgKyAjIFNlcGFyYXRlIGVmZmVjdHMgYnkgdHJhaXQgdHlwZQ0KICAgICAgICAgICAgICAgICh0cmFpdF90eXBlLTF8cmVmKSArICMgQ29ycmVsYXRpb24gYmV0d2VlbiB0cmFpdHMgYW1vbmcgc3R1ZGllcw0KICAgICAgICAgICAgICAgICgxfHNwZWNpZXMpICsgIyBTcGVjaWVzLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxncihwaHlsb2dlbnksIGNvdiA9IHBoeWxvX21hdHJpeCkpICsgIyBQaHlsb2dlbmV0aWMgcmVsYXRlZG5lc3MNCiAgICAgICAgICAgICAgICAoMXxleHBlcmltZW50X0lEKSArICMgRXhwZXJpbWVudC1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8b2JzKSArICMgT2JzZXJ2YXRpb24tbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgIGZjb3IoVkNWX2xuQ1ZSKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5DVlJfbW9kZWxfZ2VuX3NlbGVjdGlvbiA8LSBicm0oZm9ybXVsYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IGdhdXNzaWFuKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTIgPSBsaXN0KHBoeWxvX21hdHJpeCA9IHBoeWxvX21hdHJpeCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZDVl9sbkNWUiA9IFZDVl9sbkNWUiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yID0gcHJpb3IsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OSwgbWF4X3RyZWVkZXB0aCA9IDE1KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDQwMDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXJtdXAgPSAyMDAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFpbnMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEyMykgDQojIFNhdmUgbW9kZWwNCnNhdmVSRFMobG5DVlJfbW9kZWxfZ2VuX3NlbGVjdGlvbiwgZmlsZSA9ICJSRGF0YS9sbkNWUl9tb2RlbF9nZW5fc2VsZWN0aW9uLnJkcyIpDQpgYGANCg0KIyMjIyAqTW9kZWwgb3V0cHV0Kg0KYGBge3J9DQojIExvYWQgbW9kZWwNCmxuQ1ZSX21vZGVsX2dlbl9zZWxlY3Rpb24gPC0gcmVhZFJEUygiUkRhdGEvbG5DVlJfbW9kZWxfZ2VuX3NlbGVjdGlvbi5yZHMiKQ0KDQojIERpc3BsYXkgbW9kZWwgb3V0cHV0IA0Kc3VtbWFyeShsbkNWUl9tb2RlbF9nZW5fc2VsZWN0aW9uKQ0KDQojIENsZWFuZWQgbW9kZWwgb3V0cHV0DQphcy5kYXRhLmZyYW1lKGZpeGVmKGxuQ1ZSX21vZGVsX2dlbl9zZWxlY3Rpb24sIHN1bW1hcnkgPSBUUlVFKSkgJT4lDQogICMgUmVuYW1lIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBmb3IgY2xlYW5lciBkaXNwbGF5DQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAiUGFyYW1ldGVyIikgJT4lDQogIG11dGF0ZSgNCiAgICAjIFNpbXBsaWZ5IGB0cmFpdF90eXBlYCBhbmQgYHdhcm1fY29sZGAgaW50ZXJhY3Rpb25zDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKTp3YXJtX2NvbGQoY29sZHx3YXJtKSIsICJcXDEoXFwyKSIsIFBhcmFtZXRlciksDQogICAgIyBBZGp1c3QgZm9yIGFzc2F5X3RlbXBfZGlmZg0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKylcXCgoY29sZHx3YXJtKVxcKTphc3NheV90ZW1wX2RpZmYiLCAiXFwxKFxcMik6IGFzc2F5X3RlbXBfZGlmZiIsIFBhcmFtZXRlciksDQogICAgIyBSZW1vdmUgInNjYWxlIiBmcm9tIGdlbl9zZWxlY3Rpb24NCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJzY2FsZWdlbl9zZWxlY3Rpb24iLCAiZ2VuX3NlbGVjdGlvbiIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkRhdGEgdmlzdWFsaXNhdGlvbioNCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD0xMH0NCg0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucw0KZW1tZWFuc19nZW5fc2VsZWN0aW9uIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5DVlJfbW9kZWxfZ2VuX3NlbGVjdGlvbiwNCiAgc3BlY3MgPSB+IGdlbl9zZWxlY3Rpb24gfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3QoZ2VuX3NlbGVjdGlvbiA9IHNlcShtaW4oZGF0YSRnZW5fc2VsZWN0aW9uKSwgbWF4KGRhdGEkZ2VuX3NlbGVjdGlvbiksIGJ5ID0gMSksDQogICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPSAwKSkNCiAgKSAjIENvbmRpdGlvbmFsIGVmZmVjdHMgb24gYXNzYXlfdGVtcF9kaWZmID0gMA0KDQoNCiMgQ2FsY3VsYXRlIHJhbmdlIG9mIHZhbHVlcyBmb3IgZWFjaCBjYXRlZ29yeQ0KcmFuZ2VfZGYgPC0gZGF0YSAlPiUNCiAgZ3JvdXBfYnkodHJhaXRfdHlwZSwgd2FybV9jb2xkKSAlPiUNCiAgc3VtbWFyaXplKA0KICAgIG1pbl9nZW5fc2VsZWN0aW9uID0gbWluKGdlbl9zZWxlY3Rpb24pLA0KICAgIG1heF9nZW5fc2VsZWN0aW9uID0gbWF4KGdlbl9zZWxlY3Rpb24pDQogICkNCg0KZW1tZWFuc19nZW5fc2VsZWN0aW9uJHRyYWl0X3R5cGUgPC0gZmFjdG9yKGVtbWVhbnNfZ2VuX3NlbGVjdGlvbiR0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYm9keV9zaXplIiwgImZlY3VuZGl0eSIsICJzdXJ2aXZhbCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQm9keSBzaXplIiwgIkZlY3VuZGl0eSIsICJTdXJ2aXZhbCIpKQ0KDQplbW1lYW5zX2dlbl9zZWxlY3Rpb24kd2FybV9jb2xkIDwtIGZhY3RvcihlbW1lYW5zX2dlbl9zZWxlY3Rpb24kd2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiY29sZCIsICJ3YXJtIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJDb2xkIiwgIldhcm0iKSkNCg0KIyBUYWlsb3IgcHJlZGljdGlvbnMgdG8gdGhlIHJhbmdlIG9mIHRoZSBkYXRhDQplbW1lYW5zX2dlbl9zZWxlY3Rpb24gPC0gZW1tZWFuc19nZW5fc2VsZWN0aW9uICU+JQ0KICBsZWZ0X2pvaW4ocmFuZ2VfZGYsIGJ5ID0gYygidHJhaXRfdHlwZSIsICJ3YXJtX2NvbGQiKSkgJT4lDQogIGZpbHRlcigNCiAgICBnZW5fc2VsZWN0aW9uID49IG1pbl9nZW5fc2VsZWN0aW9uLA0KICAgIGdlbl9zZWxlY3Rpb24gPD0gbWF4X2dlbl9zZWxlY3Rpb24NCiAgKQ0KDQojIFBsb3QNCmdncGxvdCgpICsgDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgIyBIb3Jpem9udGFsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSkgKyANCiAgICBnZW9tX3BvaW50KGRhdGEgPSBkYXRhLCAgIyBFZmZlY3Qgc2l6ZXMsIHNjYWxlZCBieSBwcmVjaXNpb24NCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gZ2VuX3NlbGVjdGlvbiwgDQogICAgICAgICAgICAgICAgICAgICAgeSA9IGxuQ1ZSLCANCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMS9zcXJ0KHZhcl9sbkNWUiksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX2dlbl9zZWxlY3Rpb24sICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IGdlbl9zZWxlY3Rpb24sDQogICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgIGFscGhhID0gLjUpICsgDQogICAgIGdlb21fbGluZShkYXRhID0gZW1tZWFuc19nZW5fc2VsZWN0aW9uLCAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSBnZW5fc2VsZWN0aW9uLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArICANCiAgICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXMsIA0KICAgICAgICAgICAgICBhZXMoeCA9IEluZiwgDQogICAgICAgICAgICAgICAgICB5ID0gaWZlbHNlKHdhcm1fY29sZCA9PSAiV2FybSIsIC0yLCAtMi43NSksICAjIFNhbXBsZSBzaXplcw0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEuMDUsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGZhY2V0X3dyYXAofiB0cmFpdF90eXBlLCBuY29sID0gMSkgKyAgIyBEaWZmZXJlbnQgcGFuZWxzIGZvciBlYWNoIHRyYWl0DQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgbGFicyh4ID0gIk51bWJlciBvZiBnZW5lcmF0aW9ucyBvZiBzZWxlY3Rpb24iLCB5ID0gImxuQ1ZSIiwgY29sID0gIlJlZ2ltZSIpICsNCiAgdGhlbWVfYncoKSArIA0KICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDIsIDgpKSsgDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDI1LCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTgpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgICAgYXhpcy50ZXh0LnkgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwLCANCiAgICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCBoanVzdCA9IDAuNSksDQogICAgICAgICAgYXhpcy50ZXh0LnggPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuNSksDQogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMjIpKSArDQogICAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIHNpemUgPSAibm9uZSIpKw0KICAgIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygtMywgMyksDQogICAgICAgICAgICAgICAgICAgIHhsaW0gPSBjKDAsIDE1MCkpDQoNCmdnc2F2ZShmaWxlID0gImZpZy9sbkNWUl9nZW5fc2VsZWN0aW9uLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIGRwaSA9IDUwMCkNCmBgYA0KDQojIyMgKipOdW1iZXIgb2YgZ2VuZXJhdGlvbnMgb2YgY29tbW9uIGdhcmRlbioqIA0KDQojIyMjICpNb2RlbCBzcGVjaWZpY2F0aW9uKg0KYGBge3IsIGV2YWwgPSBGfQ0KIyBNb2RlbCBzcGVjaWZpY2F0aW9uDQpmb3JtdWxhIDwtIGJmKGxuQ1ZSIH4gMCArIHRyYWl0X3R5cGU6d2FybV9jb2xkICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOmFzc2F5X3RlbXBfZGlmZiArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFpdF90eXBlOndhcm1fY29sZDpzY2FsZShnZW5fY29tbW9uX2dhcmRlbikgKyAjIFNlcGFyYXRlIGVmZmVjdHMgYnkgdHJhaXQgdHlwZQ0KICAgICAgICAgICAgICAgICh0cmFpdF90eXBlLTF8cmVmKSArICMgQ29ycmVsYXRpb24gYmV0d2VlbiB0cmFpdHMgYW1vbmcgc3R1ZGllcw0KICAgICAgICAgICAgICAgICgxfHNwZWNpZXMpICsgIyBTcGVjaWVzLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxncihwaHlsb2dlbnksIGNvdiA9IHBoeWxvX21hdHJpeCkpICsgIyBQaHlsb2dlbmV0aWMgcmVsYXRlZG5lc3MNCiAgICAgICAgICAgICAgICAoMXxleHBlcmltZW50X0lEKSArICMgRXhwZXJpbWVudC1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8b2JzKSArICMgT2JzZXJ2YXRpb24tbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgIGZjb3IoVkNWX2xuQ1ZSKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5DVlJfbW9kZWxfZ2VuX2NvbW1vbl9nYXJkZW4gPC0gYnJtKGZvcm11bGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBnYXVzc2lhbigpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEyID0gbGlzdChwaHlsb19tYXRyaXggPSBwaHlsb19tYXRyaXgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWQ1ZfbG5DVlIgPSBWQ1ZfbG5DVlIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmlvciA9IHByaW9yLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXIgPSA0MDAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FybXVwID0gMjAwMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhaW5zID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZWQgPSAxMjMpIA0KIyBTYXZlIG1vZGVsDQpzYXZlUkRTKGxuQ1ZSX21vZGVsX2dlbl9jb21tb25fZ2FyZGVuLCBmaWxlID0gIlJEYXRhL2xuQ1ZSX21vZGVsX2dlbl9jb21tb25fZ2FyZGVuLnJkcyIpDQpgYGANCg0KIyMjIyAqTW9kZWwgb3V0cHV0Kg0KYGBge3J9DQojIExvYWQgbW9kZWwNCmxuQ1ZSX21vZGVsX2dlbl9jb21tb25fZ2FyZGVuIDwtIHJlYWRSRFMoIlJEYXRhL2xuQ1ZSX21vZGVsX2dlbl9jb21tb25fZ2FyZGVuLnJkcyIpDQoNCiMgRGlzcGxheSBtb2RlbCBvdXRwdXQgDQpzdW1tYXJ5KGxuQ1ZSX21vZGVsX2dlbl9jb21tb25fZ2FyZGVuKQ0KDQojIENsZWFuZWQgbW9kZWwgb3V0cHV0DQphcy5kYXRhLmZyYW1lKGZpeGVmKGxuQ1ZSX21vZGVsX2dlbl9jb21tb25fZ2FyZGVuLCBzdW1tYXJ5ID0gVFJVRSkpICU+JQ0KICAjIFJlbmFtZSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgZm9yIGNsZWFuZXIgZGlzcGxheQ0KICByb3duYW1lc190b19jb2x1bW4odmFyID0gIlBhcmFtZXRlciIpICU+JQ0KICBtdXRhdGUoDQogICAgIyBTaW1wbGlmeSBgdHJhaXRfdHlwZWAgYW5kIGB3YXJtX2NvbGRgIGludGVyYWN0aW9ucw0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKyk6d2FybV9jb2xkKGNvbGR8d2FybSkiLCAiXFwxKFxcMikiLCBQYXJhbWV0ZXIpLA0KICAgICMgQWRqdXN0IGZvciBhc3NheV90ZW1wX2RpZmYNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspXFwoKGNvbGR8d2FybSlcXCk6YXNzYXlfdGVtcF9kaWZmIiwgIlxcMShcXDIpOiBhc3NheV90ZW1wX2RpZmYiLCBQYXJhbWV0ZXIpLA0KICAgICMgUmVtb3ZlICJzY2FsZSIgZnJvbSBnZW5fY29tbW9uX2dhcmRlbg0KICAgIFBhcmFtZXRlciA9IGdzdWIoInNjYWxlZ2VuX2NvbW1vbl9nYXJkZW4iLCAiZ2VuX2NvbW1vbl9nYXJkZW4iLCBQYXJhbWV0ZXIpDQogICkgJT4lDQogICMgUm91bmQgbnVtYmVycyB0byAzIGRlY2ltYWwgcG9pbnRzDQogIG11dGF0ZShhY3Jvc3MoYyhFc3RpbWF0ZSwgUTIuNSwgUTk3LjUpLCB+IHJvdW5kKC4sIDMpKSkgJT4lDQogIHNlbGVjdChQYXJhbWV0ZXIsIEVzdGltYXRlLCBgTG93ZXIgQ0lgID0gUTIuNSwgYFVwcGVyIENJYCA9IFE5Ny41KSAlPiUNCiAga2FibGUoKSAlPiUNCiAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImNlbnRlciIsIGZpeGVkX3RoZWFkID0gVFJVRSkgJT4lDQogIGNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFLCBib3JkZXJfcmlnaHQgPSBUUlVFKSAlPiUNCiAgcm93X3NwZWMoMCwgYmFja2dyb3VuZCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIiwgYm9sZCA9IFRSVUUpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZpeGVkX3RoZWFkID0gVFJVRSkNCmBgYA0KDQojIyMjICpEYXRhIHZpc3VhbGlzYXRpb24qDQpgYGB7ciwgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQ9MTB9DQoNCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4gPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsbkNWUl9tb2RlbF9nZW5fY29tbW9uX2dhcmRlbiwNCiAgc3BlY3MgPSB+IGdlbl9jb21tb25fZ2FyZGVuIHwgdHJhaXRfdHlwZSAqIHdhcm1fY29sZCwNCiAgYXQgPSBsaXN0KGdlbl9jb21tb25fZ2FyZGVuID0gc2VxKG1pbihkYXRhJGdlbl9jb21tb25fZ2FyZGVuKSwgbWF4KGRhdGEkZ2VuX2NvbW1vbl9nYXJkZW4pLCBieSA9IDEpLA0KICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID0gMCkpDQogICkgIyBDb25kaXRpb25hbCBlZmZlY3RzIG9uIGFzc2F5X3RlbXBfZGlmZiA9IDANCg0KIyBDYWxjdWxhdGUgcmFuZ2Ugb2YgdmFsdWVzIGZvciBlYWNoIGNhdGVnb3J5DQpyYW5nZV9kZiA8LSBkYXRhICU+JQ0KICBncm91cF9ieSh0cmFpdF90eXBlLCB3YXJtX2NvbGQpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWluX2dlbl9jb21tb25fZ2FyZGVuID0gbWluKGdlbl9jb21tb25fZ2FyZGVuKSwNCiAgICBtYXhfZ2VuX2NvbW1vbl9nYXJkZW4gPSBtYXgoZ2VuX2NvbW1vbl9nYXJkZW4pDQogICkNCg0KZW1tZWFuc19nZW5fY29tbW9uX2dhcmRlbiR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX2dlbl9jb21tb25fZ2FyZGVuJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4kd2FybV9jb2xkIDwtIGZhY3RvcihlbW1lYW5zX2dlbl9jb21tb25fZ2FyZGVuJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgVGFpbG9yIHByZWRpY3Rpb25zIHRvIHRoZSByYW5nZSBvZiB0aGUgZGF0YQ0KZW1tZWFuc19nZW5fY29tbW9uX2dhcmRlbiA8LSBlbW1lYW5zX2dlbl9jb21tb25fZ2FyZGVuICU+JQ0KICBsZWZ0X2pvaW4ocmFuZ2VfZGYsIGJ5ID0gYygidHJhaXRfdHlwZSIsICJ3YXJtX2NvbGQiKSkgJT4lDQogIGZpbHRlcigNCiAgICBnZW5fY29tbW9uX2dhcmRlbiA+PSBtaW5fZ2VuX2NvbW1vbl9nYXJkZW4sDQogICAgZ2VuX2NvbW1vbl9nYXJkZW4gPD0gbWF4X2dlbl9jb21tb25fZ2FyZGVuDQogICkNCg0KIyBQbG90DQpnZ3Bsb3QoKSArIA0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUpICsgDQogICAgZ2VvbV9wb2ludChkYXRhID0gZGF0YSwgICMgRWZmZWN0IHNpemVzLCBzY2FsZWQgYnkgcHJlY2lzaW9uDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IGdlbl9jb21tb25fZ2FyZGVuLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5DVlIsIA0KICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxL3NxcnQodmFyX2xuQ1ZSKSwgDQogICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwgDQogICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNywgDQogICAgICAgICAgICAgICAgICBzdHJva2UgPSAxLA0KICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjA1KSkgKyANCiAgICAgZ2VvbV9yaWJib24oZGF0YSA9IGVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4sICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IGdlbl9jb21tb25fZ2FyZGVuLA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICBhbHBoYSA9IC41KSArIA0KICAgICBnZW9tX2xpbmUoZGF0YSA9IGVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4sICMgUHJlZGljdGVkIHJlZ3Jlc3Npb24gbGluZQ0KICAgICAgICAgICAgICAgYWVzKHkgPSBlbW1lYW4sDQogICAgICAgICAgICAgICAgICAgeCA9IGdlbl9jb21tb25fZ2FyZGVuLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArICANCiAgICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXMsIA0KICAgICAgICAgICAgICBhZXMoeCA9IEluZiwgDQogICAgICAgICAgICAgICAgICB5ID0gaWZlbHNlKHdhcm1fY29sZCA9PSAiV2FybSIsIC0yLCAtMi43NSksICAjIFNhbXBsZSBzaXplcw0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEuMDUsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGZhY2V0X3dyYXAofiB0cmFpdF90eXBlLCBuY29sID0gMSkgKyAgIyBEaWZmZXJlbnQgcGFuZWxzIGZvciBlYWNoIHRyYWl0DQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgbGFicyh4ID0gIk51bWJlciBvZiBnZW5lcmF0aW9ucyBvZiBjb21tb24gZ2FyZGVuIiwgeSA9ICJsbkNWUiIsIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCA4KSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNSwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIyKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTMsIDMpLA0KICAgICAgICAgICAgICAgICAgICB4bGltID0gYygwLCAxMikpDQoNCmdnc2F2ZShmaWxlID0gImZpZy9sbkNWUl9nZW5fY29tbW9uX2dhcmRlbi5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA3LCBkcGkgPSA1MDApDQpgYGANCg0KIyMjICoqUG9wdWxhdGlvbiBzaXplKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5DVlIgfiAwICsgdHJhaXRfdHlwZTp3YXJtX2NvbGQgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhaXRfdHlwZTp3YXJtX2NvbGQ6YXNzYXlfdGVtcF9kaWZmICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOnNjYWxlKHBvcF9zaXplKSArICMgU2VwYXJhdGUgZWZmZWN0cyBieSB0cmFpdCB0eXBlDQogICAgICAgICAgICAgICAgKHRyYWl0X3R5cGUtMXxyZWYpICsgIyBDb3JyZWxhdGlvbiBiZXR3ZWVuIHRyYWl0cyBhbW9uZyBzdHVkaWVzDQogICAgICAgICAgICAgICAgKDF8c3BlY2llcykgKyAjIFNwZWNpZXMtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfGdyKHBoeWxvZ2VueSwgY292ID0gcGh5bG9fbWF0cml4KSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5DVlIpKSAjIFZhcmlhbmNlIGNvdmFyaWFuY2UgbWF0aXggb2YgY29ycmVsYXRlZCBzYW1wbGluZyB2YXJpYW5jZXMNCg0KIyBEZWZpbmUgcHJpb3JzDQpwcmlvciA9IGMoDQogIHByaW9yKGNvbnN0YW50KDEpLCBjbGFzcyA9ICJzaWdtYSIpDQopICMgQmVjYXVzZSB0aGUgcmVzaWR1YWwgdmFyaWFuY2UtY292YXJpYW5jZSBzdHJ1Y3R1cmUgaXMgc3BlY2lmaWVkIGluIGZjb3IsIHRoZXJlIGlzIG5vIG5lZWQgdG8gZXN0aW1hdGUgc2lnbWEgc28gaXQgaXMgbGVmdCBhcyBhIGNvbnN0YW50DQoNCiMgRml0IG1vZGVsDQpsbkNWUl9tb2RlbF9wb3Bfc2l6ZSA8LSBicm0oZm9ybXVsYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IGdhdXNzaWFuKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTIgPSBsaXN0KHBoeWxvX21hdHJpeCA9IHBoeWxvX21hdHJpeCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZDVl9sbkNWUiA9IFZDVl9sbkNWUiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yID0gcHJpb3IsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OSwgbWF4X3RyZWVkZXB0aCA9IDE1KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDQwMDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXJtdXAgPSAyMDAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFpbnMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEyMykgDQojIFNhdmUgbW9kZWwNCnNhdmVSRFMobG5DVlJfbW9kZWxfcG9wX3NpemUsIGZpbGUgPSAiUkRhdGEvbG5DVlJfbW9kZWxfcG9wX3NpemUucmRzIikNCmBgYA0KDQojIyMjICpNb2RlbCBvdXRwdXQqDQpgYGB7cn0NCiMgTG9hZCBtb2RlbA0KbG5DVlJfbW9kZWxfcG9wX3NpemUgPC0gcmVhZFJEUygiUkRhdGEvbG5DVlJfbW9kZWxfcG9wX3NpemUucmRzIikNCg0KIyBEaXNwbGF5IG1vZGVsIG91dHB1dCANCnN1bW1hcnkobG5DVlJfbW9kZWxfcG9wX3NpemUpDQoNCiMgQ2xlYW5lZCBtb2RlbCBvdXRwdXQNCmFzLmRhdGEuZnJhbWUoZml4ZWYobG5DVlJfbW9kZWxfcG9wX3NpemUsIHN1bW1hcnkgPSBUUlVFKSkgJT4lDQogICMgUmVuYW1lIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBmb3IgY2xlYW5lciBkaXNwbGF5DQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAiUGFyYW1ldGVyIikgJT4lDQogIG11dGF0ZSgNCiAgICAjIFNpbXBsaWZ5IGB0cmFpdF90eXBlYCBhbmQgYHdhcm1fY29sZGAgaW50ZXJhY3Rpb25zDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKTp3YXJtX2NvbGQoY29sZHx3YXJtKSIsICJcXDEoXFwyKSIsIFBhcmFtZXRlciksDQogICAgIyBBZGp1c3QgZm9yIGFzc2F5X3RlbXBfZGlmZg0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKylcXCgoY29sZHx3YXJtKVxcKTphc3NheV90ZW1wX2RpZmYiLCAiXFwxKFxcMik6IGFzc2F5X3RlbXBfZGlmZiIsIFBhcmFtZXRlciksDQogICAgIyBSZW1vdmUgInNjYWxlIiBmcm9tIHBvcF9zaXplDQogICAgUGFyYW1ldGVyID0gZ3N1Yigic2NhbGVwb3Bfc2l6ZSIsICJwb3Bfc2l6ZSIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KDQpgYGANCg0KIyMjIyAqRGF0YSB2aXN1YWxpc2F0aW9uKg0KYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0PTEwfQ0KDQojIEdlbmVyYXRlIHByZWRpY3Rpb25zDQplbW1lYW5zX3BvcF9zaXplIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5DVlJfbW9kZWxfcG9wX3NpemUsDQogIHNwZWNzID0gfiBwb3Bfc2l6ZSB8IHRyYWl0X3R5cGUgKiB3YXJtX2NvbGQsDQogIGF0ID0gbGlzdChwb3Bfc2l6ZSA9IHNlcShtaW4oZGF0YSRwb3Bfc2l6ZSwgbmEucm09VCksIG1heChkYXRhJHBvcF9zaXplLCBuYS5ybT1UKSwgYnkgPSA1MCksDQogICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPSAwKSkNCiAgKSAjIENvbmRpdGlvbmFsIGVmZmVjdHMgb24gYXNzYXlfdGVtcF9kaWZmID0gMA0KDQojIENhbGN1bGF0ZSByYW5nZSBvZiB2YWx1ZXMgZm9yIGVhY2ggY2F0ZWdvcnkNCnJhbmdlX2RmIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtaW5fcG9wX3NpemUgPSBtaW4ocG9wX3NpemUsIG5hLnJtPVQpLA0KICAgIG1heF9wb3Bfc2l6ZSA9IG1heChwb3Bfc2l6ZSwgbmEucm09VCkNCiAgKQ0KDQplbW1lYW5zX3BvcF9zaXplJHRyYWl0X3R5cGUgPC0gZmFjdG9yKGVtbWVhbnNfcG9wX3NpemUkdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KZW1tZWFuc19wb3Bfc2l6ZSR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfcG9wX3NpemUkd2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiY29sZCIsICJ3YXJtIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJDb2xkIiwgIldhcm0iKSkNCg0KIyBUYWlsb3IgcHJlZGljdGlvbnMgdG8gdGhlIHJhbmdlIG9mIHRoZSBkYXRhDQplbW1lYW5zX3BvcF9zaXplIDwtIGVtbWVhbnNfcG9wX3NpemUgJT4lDQogIGxlZnRfam9pbihyYW5nZV9kZiwgYnkgPSBjKCJ0cmFpdF90eXBlIiwgIndhcm1fY29sZCIpKSAlPiUNCiAgZmlsdGVyKA0KICAgIHBvcF9zaXplID49IG1pbl9wb3Bfc2l6ZSwNCiAgICBwb3Bfc2l6ZSA8PSBtYXhfcG9wX3NpemUNCiAgKQ0KDQojIENhbGN1bGF0ZSBzYW1wbGUgc2l6ZXMgYW5kIHN0dWR5IGNvdW50cyBmb3IgcG9wdWxhdGlvbiBzaXplDQpzYW1wbGVfc2l6ZXNfcG9wX3NpemUgPC0gZGF0YSAlPiUNCiAgZmlsdGVyKGlzLm5hKHBvcF9zaXplKT09RkFMU0UpICU+JSANCiAgZ3JvdXBfYnkodHJhaXRfdHlwZSwgd2FybV9jb2xkKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGVzdGltYXRlcyA9IG4oKSwNCiAgICBzdHVkaWVzID0gbl9kaXN0aW5jdChyZWYpDQogICkNCg0KIyBQbG90DQpnZ3Bsb3QoKSArIA0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUpICsgDQogICAgZ2VvbV9wb2ludChkYXRhID0gZGF0YSwgICMgRWZmZWN0IHNpemVzLCBzY2FsZWQgYnkgcHJlY2lzaW9uDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHBvcF9zaXplLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5DVlIsIA0KICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxL3NxcnQodmFyX2xuQ1ZSKSwgDQogICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwgDQogICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNywgDQogICAgICAgICAgICAgICAgICBzdHJva2UgPSAxLA0KICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjA1KSkgKyANCiAgICAgZ2VvbV9yaWJib24oZGF0YSA9IGVtbWVhbnNfcG9wX3NpemUsICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IHBvcF9zaXplLA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICBhbHBoYSA9IC41KSArIA0KICAgICBnZW9tX2xpbmUoZGF0YSA9IGVtbWVhbnNfcG9wX3NpemUsICMgUHJlZGljdGVkIHJlZ3Jlc3Npb24gbGluZQ0KICAgICAgICAgICAgICAgYWVzKHkgPSBlbW1lYW4sDQogICAgICAgICAgICAgICAgICAgeCA9IHBvcF9zaXplLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArICANCiAgICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXNfcG9wX3NpemUsIA0KICAgICAgICAgICAgICBhZXMoeCA9IEluZiwgDQogICAgICAgICAgICAgICAgICB5ID0gaWZlbHNlKHdhcm1fY29sZCA9PSAiV2FybSIsIC0yLCAtMi43NSksICAjIFNhbXBsZSBzaXplcw0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEuMDUsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGZhY2V0X3dyYXAofiB0cmFpdF90eXBlLCBuY29sID0gMSkgKyAgIyBEaWZmZXJlbnQgcGFuZWxzIGZvciBlYWNoIHRyYWl0DQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgbGFicyh4ID0gIlBvcHVsYXRpb24gc2l6ZSIsIHkgPSAibG5DVlIiLCBjb2wgPSAiUmVnaW1lIikgKw0KICB0aGVtZV9idygpICsgDQogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgOCkpKyANCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjUsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxOCksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAyMikpICsNCiAgICBndWlkZXMoZmlsbCA9ICJub25lIiwgc2l6ZSA9ICJub25lIikrDQogICAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0zLCAzKSkNCg0KZ2dzYXZlKGZpbGUgPSAiZmlnL2xuQ1ZSX3BvcF9zaXplLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIGRwaSA9IDUwMCkNCmBgYA0KDQoNCiMjIyAqKkFsbCBtb2RlcmF0b3JzKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5DVlIgfiAwICsgdHJhaXRfdHlwZTp3YXJtX2NvbGQgKyANCiAgICAgICAgICAgICAgICB0cmFpdF90eXBlOndhcm1fY29sZDphc3NheV90ZW1wX2RpZmYgKyANCiAgICAgICAgICAgICAgICB0cmFpdF90eXBlOndhcm1fY29sZDpzY2FsZShzZWxlY3RfdGVtcF9kaWZmKSArDQogICAgICAgICAgICAgICAgdHJhaXRfdHlwZTp3YXJtX2NvbGQ6c2NhbGUoZ2VuX3NlbGVjdGlvbikgKyANCiAgICAgICAgICAgICAgICB0cmFpdF90eXBlOndhcm1fY29sZDpzY2FsZShnZW5fY29tbW9uX2dhcmRlbikgKyAjIFNlcGFyYXRlIGVmZmVjdHMgYnkgdHJhaXQgdHlwZQ0KICAgICAgICAgICAgICAgICh0cmFpdF90eXBlLTF8cmVmKSArICMgQ29ycmVsYXRpb24gYmV0d2VlbiB0cmFpdHMgYW1vbmcgc3R1ZGllcw0KICAgICAgICAgICAgICAgICgxfHNwZWNpZXMpICsgIyBTcGVjaWVzLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxncihwaHlsb2dlbnksIGNvdiA9IHBoeWxvX21hdHJpeCkpICsgIyBQaHlsb2dlbmV0aWMgcmVsYXRlZG5lc3MNCiAgICAgICAgICAgICAgICAoMXxleHBlcmltZW50X0lEKSArICMgRXhwZXJpbWVudC1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8b2JzKSArICMgT2JzZXJ2YXRpb24tbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgIGZjb3IoVkNWX2xuQ1ZSKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5DVlJfbW9kZWxfYWxsX21vZGVyYXRvcnMgPC0gYnJtKGZvcm11bGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IGdhdXNzaWFuKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEyID0gbGlzdChwaHlsb19tYXRyaXggPSBwaHlsb19tYXRyaXgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZDVl9sbkNWUiA9IFZDVl9sbkNWUiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IgPSBwcmlvciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDQwMDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm11cCA9IDIwMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhaW5zID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gMTIzKSANCg0KIyBTYXZlIG1vZGVsDQpzYXZlUkRTKGxuQ1ZSX21vZGVsX2FsbF9tb2RlcmF0b3JzLCBmaWxlID0gIlJEYXRhL2xuQ1ZSX21vZGVsX2FsbF9tb2RlcmF0b3JzLnJkcyIpDQpgYGANCg0KIyMjIyAqTW9kZWwgb3V0cHV0Kg0KYGBge3J9DQojIExvYWQgbW9kZWwNCmxuQ1ZSX21vZGVsX2FsbF9tb2RlcmF0b3JzIDwtIHJlYWRSRFMoIlJEYXRhL2xuQ1ZSX21vZGVsX2FsbF9tb2RlcmF0b3JzLnJkcyIpDQoNCiMgRGlzcGxheSBtb2RlbCBvdXRwdXQgDQpzdW1tYXJ5KGxuQ1ZSX21vZGVsX2FsbF9tb2RlcmF0b3JzKQ0KDQojIENsZWFuZWQgbW9kZWwgb3V0cHV0DQphcy5kYXRhLmZyYW1lKGZpeGVmKGxuQ1ZSX21vZGVsX2FsbF9tb2RlcmF0b3JzLCBzdW1tYXJ5ID0gVFJVRSkpICU+JQ0KICAjIFJlbmFtZSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgZm9yIGNsZWFuZXIgZGlzcGxheQ0KICByb3duYW1lc190b19jb2x1bW4odmFyID0gIlBhcmFtZXRlciIpICU+JQ0KICBtdXRhdGUoDQogICAgIyBTaW1wbGlmeSBgdHJhaXRfdHlwZWAgYW5kIGB3YXJtX2NvbGRgIGludGVyYWN0aW9ucw0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKyk6d2FybV9jb2xkKGNvbGR8d2FybSkiLCAiXFwxKFxcMikiLCBQYXJhbWV0ZXIpLA0KICAgICMgQWRqdXN0IGZvciBhc3NheV90ZW1wX2RpZmYNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspXFwoKGNvbGR8d2FybSlcXCk6YXNzYXlfdGVtcF9kaWZmIiwgIlxcMShcXDIpOiBhc3NheV90ZW1wX2RpZmYiLCBQYXJhbWV0ZXIpLA0KICAgICMgUmVtb3ZlICJzY2FsZSIgZnJvbSBhbGwgbW9kZXJhdG9yIHZhcmlhYmxlcw0KICAgIFBhcmFtZXRlciA9IGdzdWIoInNjYWxlIiwgIiIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KDQojIEdlbmVyYXRlIHByZWRpY3RlZCB2YWx1ZXMgYXQgZGlmZmVyZW50IGFzc2F5IHRlbXBlcmF0dXJlcw0KZW1tZWFuc19mdWxsX21vZGVsIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5DVlJfbW9kZWxfYWxsX21vZGVyYXRvcnMsDQogIHNwZWNzID0gfiBhc3NheV90ZW1wX2RpZmYgKiBzZWxlY3RfdGVtcF9kaWZmICogZ2VuX3NlbGVjdGlvbiAqIGdlbl9jb21tb25fZ2FyZGVuIHwgdHJhaXRfdHlwZSAqIHdhcm1fY29sZCwNCiAgYXQgPSBsaXN0KGFzc2F5X3RlbXBfZGlmZiA9IGMoLTguNSwgLTQsIDAsIDQsIDUsIC01LCAxNywgMjApKSAjIFByZWRpY3QgYXQgdW5pcXVlIG1pbiwgY29udHJvbCwgbWF4IHZhbHVlcw0KKSkNCg0KIyBDYWxjdWxhdGUgcmFuZ2Ugb2YgdmFsdWVzIGZvciBlYWNoIGNhdGVnb3J5DQpyYW5nZV9kZiA8LSBkYXRhICU+JQ0KICBncm91cF9ieSh0cmFpdF90eXBlLCB3YXJtX2NvbGQpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWluX2Fzc2F5ID0gbWluKGFzc2F5X3RlbXBfZGlmZiksDQogICAgbWF4X2Fzc2F5ID0gbWF4KGFzc2F5X3RlbXBfZGlmZiksDQogICAgY29udHJvbF9hc3NheSA9IDANCiAgKQ0KDQplbW1lYW5zX2Z1bGxfbW9kZWwkdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19mdWxsX21vZGVsJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfZnVsbF9tb2RlbCR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfZnVsbF9tb2RlbCR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KDQojIFRhaWxvciBwcmVkaWN0aW9ucyB0byB0aGUgcmFuZ2Ugb2YgdGhlIGRhdGENCmVtbWVhbnNfZnVsbF9tb2RlbCAlPiUNCiAgbGVmdF9qb2luKHJhbmdlX2RmLCBieSA9IGMoInRyYWl0X3R5cGUiLCAid2FybV9jb2xkIikpICU+JQ0KICBmaWx0ZXIoDQogICAgYXNzYXlfdGVtcF9kaWZmID09IG1pbl9hc3NheSB8DQogICAgYXNzYXlfdGVtcF9kaWZmID09IG1heF9hc3NheSB8DQogICAgYXNzYXlfdGVtcF9kaWZmID09IGNvbnRyb2xfYXNzYXkpICU+JSANCiAgICBkcGx5cjo6c2VsZWN0KC1taW5fYXNzYXksIC1tYXhfYXNzYXksIC1jb250cm9sX2Fzc2F5KSAlPiUgDQogICAgbXV0YXRlKHBlcmNlbnRhZ2VfY2hhbmdlID0gKGV4cChlbW1lYW4pIC0gMSkgKiAxMDAsDQogICAgICAgICAgIHBlcmNlbnRhZ2VfbG93ZXJfSFBEID0gKGV4cChsb3dlci5IUEQpIC0gMSkgKiAxMDAsDQogICAgICAgICAgIHBlcmNlbnRhZ2VfdXBwZXJfSFBEID0gKGV4cCh1cHBlci5IUEQpIC0gMSkgKiAxMDApICU+JQ0KICBtdXRhdGUoYWNyb3NzKGMoZW1tZWFuLCANCiAgICAgICAgICAgICAgICAgIGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgcGVyY2VudGFnZV9jaGFuZ2UsDQogICAgICAgICAgICAgICAgICBwZXJjZW50YWdlX2xvd2VyX0hQRCwgDQogICAgICAgICAgICAgICAgICBwZXJjZW50YWdlX3VwcGVyX0hQRCksIH4gcm91bmQoLiwgMykpKSAlPiUgICAjIFJvdW5kIG51bWJlcnMgdG8gMyBkZWNpbWFsIHBvaW50cw0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkRhdGEgdmlzdWFsaXNhdGlvbioNCg0KKipNYXJnaW5hbCBtZWFucyoqIA0KYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0PTEwfQ0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucyBhdCBhc3NheV90ZW1wX2RpZmYgPSAwLCBvciA1IGRlZ3JlZXMgYmVsb3cgb3IgYWJvdmUgdGhlIGNvbnRyb2wgdGVtcGVyYXR1cmVzDQplbW1lYW5zX2Z1bGxfbW9kZWwgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsbkNWUl9tb2RlbF9hbGxfbW9kZXJhdG9ycywNCiAgc3BlY3MgPSB+IGFzc2F5X3RlbXBfZGlmZiAqIHNlbGVjdF90ZW1wX2RpZmYgKiBnZW5fc2VsZWN0aW9uICogZ2VuX2NvbW1vbl9nYXJkZW4gfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3QoYXNzYXlfdGVtcF9kaWZmID0gYygtNSwgMCwgNSkgIyBSZS1hY2NsaW1hdGVkIHRvIGNvbnRyb2wsIG9yIDUgZGVncmVlcyBhYm92ZS9iZWxvdyB0aGUgY29udG9sDQogICkpKSANCg0KIyBSZW5hbWUgdmFyaWFibGUgbGV2ZWxzDQplbW1lYW5zX2Z1bGxfbW9kZWwkdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19mdWxsX21vZGVsJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfZnVsbF9tb2RlbCR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfZnVsbF9tb2RlbCR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KZW1tZWFuc19mdWxsX21vZGVsDQoNCiMgUGxvdA0KZ2dwbG90KCkgKw0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUsIA0KICAgICAgICAgICAgICAgbHdkPTEpICsNCiAgICBnZW9tX3F1YXNpcmFuZG9tKGRhdGEgPSBkYXRhLCAgICAgIyBQbG90IGVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGxuQ1ZSLCANCiAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gdHJhaXRfdHlwZTp3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxL3NxcnQodmFyX2xuQ1ZSKSksIA0KICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLA0KICAgICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4zLCANCiAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gMC4zKSArDQogICAgZ2VvbV9lcnJvcmJhcihkYXRhID0gZmlsdGVyKGVtbWVhbnNfZnVsbF9tb2RlbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID09ICItNSIpLCAgIyA1IGRlZ3JlZXMgYmVsb3cgY29udHJvbCAoYmFja2dyb3VuZCkNCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTp3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQpLCANCiAgICAgICAgICAgICAgICAgIGNvbG9yPSJ3aGl0ZSIsDQogICAgICAgICAgICAgICAgICBzaXplID0gMi43NSwNCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4xNiwNCiAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fbnVkZ2UoeD0tMC4yNSkpICsNCiAgICBnZW9tX3BvaW50KGRhdGEgPSBmaWx0ZXIoZW1tZWFuc19mdWxsX21vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPT0gIi01IiksICAjIDUgZGVncmVlcyBiZWxvdyBjb250cm9sIChiYWNrZ3JvdW5kKQ0KICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgeSA9IGVtbWVhbiksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDQuNSwgDQogICAgICAgICAgICAgICBzdHJva2UgPSAyLA0KICAgICAgICAgICAgICAgY29sb3I9IndoaXRlIiwNCiAgICAgICAgICAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4PS0wLjI1KSkgKw0KICAgIGdlb21fZXJyb3JiYXIoZGF0YSA9IGZpbHRlcihlbW1lYW5zX2Z1bGxfbW9kZWwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2F5X3RlbXBfZGlmZiA9PSAiLTUiKSwgIyA1IGRlZ3JlZXMgYmVsb3cgY29udHJvbCAoY3JlZGlibGUgaW50ZXJ2YWxzKQ0KICAgICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCksIA0KICAgICAgICAgICAgICAgICAgY29sb3I9IiMwNkI0QkEiLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIsDQogICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMTIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9LTAuMjUpKSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gZmlsdGVyKGVtbWVhbnNfZnVsbF9tb2RlbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID09ICItNSIpLCAjIDUgZGVncmVlcyBiZWxvdyBjb250cm9sICAocG9pbnQgZXN0aW1hdGVzKQ0KICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgeSA9IGVtbWVhbiksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDMuNSwgDQogICAgICAgICAgICAgICBzdHJva2UgPSAyLA0KICAgICAgICAgICAgICAgY29sb3I9IiMwNkI0QkEiLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9LTAuMjUpKSArDQoNCiAgICAgIGdlb21fZXJyb3JiYXIoZGF0YSA9IGZpbHRlcihlbW1lYW5zX2Z1bGxfbW9kZWwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2F5X3RlbXBfZGlmZiA9PSAiMCIpLCAgIyBjb250cm9sIHRlbXBlcmF0dXJlIChiYWNrZ3JvdW5kKQ0KICAgICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCksIA0KICAgICAgICAgICAgICAgICAgY29sb3I9IndoaXRlIiwNCiAgICAgICAgICAgICAgICAgIHNpemUgPSAyLjc1LA0KICAgICAgICAgICAgICAgICAgd2lkdGggPSAwLjE2LA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4PTApKSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gZmlsdGVyKGVtbWVhbnNfZnVsbF9tb2RlbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID09ICIwIiksICAjIGNvbnRyb2wgdGVtcGVyYXR1cmUgKGJhY2tncm91bmQpDQogICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICB5ID0gZW1tZWFuKSwNCiAgICAgICAgICAgICAgIHNoYXBlID0gMjIsDQogICAgICAgICAgICAgICBzaXplID0gNC41LCANCiAgICAgICAgICAgICAgIHN0cm9rZSA9IDIsDQogICAgICAgICAgICAgICBjb2xvcj0id2hpdGUiLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9MCkpICsNCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBmaWx0ZXIoZW1tZWFuc19mdWxsX21vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPT0gIjAiKSwgIyBjb250cm9sIHRlbXBlcmF0dXJlIChjcmVkaWJsZSBpbnRlcnZhbHMpDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBEKSwgDQogICAgICAgICAgICAgICAgICBjb2xvcj0iYmxhY2siLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIsDQogICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMTIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9MCkpICsNCiAgICBnZW9tX3BvaW50KGRhdGEgPSBmaWx0ZXIoZW1tZWFuc19mdWxsX21vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPT0gIjAiKSwgIyBjb250cm9sIHRlbXBlcmF0dXJlIChwb2ludCBlc3RpbWF0ZXMpDQogICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICB5ID0gZW1tZWFuKSwNCiAgICAgICAgICAgICAgIHNoYXBlID0gMjIsDQogICAgICAgICAgICAgICBzaXplID0gMy41LCANCiAgICAgICAgICAgICAgIHN0cm9rZSA9IDIsDQogICAgICAgICAgICAgICBjb2xvcj0iYmxhY2siLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9MCkpICsNCiAgDQogICAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBmaWx0ZXIoZW1tZWFuc19mdWxsX21vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPT0gIjUiKSwgICMgNSBkZWdyZWVzIGFib3ZlIGNvbnRyb2wgKGJhY2tncm91bmQpDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBEKSwgDQogICAgICAgICAgICAgICAgICBjb2xvcj0id2hpdGUiLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIuNzUsDQogICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMTYsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9MC4yNSkpICsNCiAgICBnZW9tX3BvaW50KGRhdGEgPSBmaWx0ZXIoZW1tZWFuc19mdWxsX21vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPT0gIjUiKSwgICMgNSBkZWdyZWVzIGFib3ZlIGNvbnRyb2wgKGJhY2tncm91bmQpDQogICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICB5ID0gZW1tZWFuKSwNCiAgICAgICAgICAgICAgIHNoYXBlID0gMjMsDQogICAgICAgICAgICAgICBzaXplID0gNC41LCANCiAgICAgICAgICAgICAgIHN0cm9rZSA9IDIsDQogICAgICAgICAgICAgICBjb2xvcj0id2hpdGUiLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9MC4yNSkpICsNCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBmaWx0ZXIoZW1tZWFuc19mdWxsX21vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPT0gIjUiKSwgIyA1IGRlZ3JlZXMgYWJvdmUgY29udHJvbCAoY3JlZGlibGUgaW50ZXJ2YWxzKQ0KICAgICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCksIA0KICAgICAgICAgICAgICAgICAgY29sb3I9IiNFODA3NTYiLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIsDQogICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMTIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9MC4yNSkpICsNCiAgICBnZW9tX3BvaW50KGRhdGEgPSBmaWx0ZXIoZW1tZWFuc19mdWxsX21vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPT0gIjUiKSwgIyA1IGRlZ3JlZXMgYWJvdmUgY29udHJvbCAocG9pbnQgZXN0aW1hdGVzKQ0KICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgeSA9IGVtbWVhbiksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIzLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDMuNSwgDQogICAgICAgICAgICAgICBzdHJva2UgPSAyLA0KICAgICAgICAgICAgICAgY29sb3I9IiNFODA3NTYiLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9MC4yNSkpICsNCiAgDQogICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXMsICAjIFNhbXBsZSBzaXplIGFubm90YXRpb25zIA0KICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgIHkgPSAzLA0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIA0KICAgIHRoZW1lX2J3KCkgKyAgICAgIyBDdXN0b21pemUgdGhlIHBsb3QNCiAgICBsYWJzKHkgPSAibG5DVlIiLCB4ID0gIiIpICsNCiAgICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDIsIDgpKSsgDQogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IiwgIiMwNkI0QkEiLCAiI0U4MDc1NiIsICIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIkNvbGQiID0gIiMwNkI0QkEiLCAiV2FybSIgPSAiI0U4MDc1NiIpKSArICAjIFRleHQgY29sb3VyDQogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpKSArDQogICAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIHNpemUgPSAibm9uZSIpKw0KICAgIGNvb3JkX2ZsaXAoKSArIA0KICAgIHlsaW0oLTMsIDMpDQoNCmdnc2F2ZShmaWxlID0gImZpZy9sbkNWUl9hbGxfbW9kZXJhdG9yc19tYXJnaW5hbF9tZWFucy5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA4LCBkcGkgPSA1MDApDQpgYGANCg0KKipPdmVyYWxsIHRyZW5kIHdpdGggYXNzYXkgdGVtcGVyYXR1cmUqKiANCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD0xMH0NCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMgZm9yIGFsbCBhc3NheSB0ZW1wZXJhdHVyZXMNCmVtbWVhbnNfZnVsbF9tb2RlbF9hc3NheSA8LSBhcy5kYXRhLmZyYW1lKGVtbWVhbnMoDQogIGxuQ1ZSX21vZGVsX2FsbF9tb2RlcmF0b3JzLA0KICBzcGVjcyA9IH4gYXNzYXlfdGVtcF9kaWZmICogc2VsZWN0X3RlbXBfZGlmZiAqIGdlbl9zZWxlY3Rpb24gKiBnZW5fY29tbW9uX2dhcmRlbiB8IHRyYWl0X3R5cGUgKiB3YXJtX2NvbGQsDQogIGF0ID0gbGlzdChhc3NheV90ZW1wX2RpZmYgPSBzZXEobWluKGRhdGEkYXNzYXlfdGVtcF9kaWZmKSwgbWF4KGRhdGEkYXNzYXlfdGVtcF9kaWZmKSwgYnkgPSAwLjUpICMgUmUtYWNjbGltYXRlZCB0byBjb250cm9sLCBvciA1IGRlZ3JlZXMgYWJvdmUvYmVsb3cgdGhlIGNvbnRvbA0KICApKSkgDQoNCiMgQ2FsY3VsYXRlIHJhbmdlIG9mIHZhbHVlcyBmb3IgZWFjaCBjYXRlZ29yeQ0KcmFuZ2VfZGYgPC0gZGF0YSAlPiUNCiAgZ3JvdXBfYnkodHJhaXRfdHlwZSwgd2FybV9jb2xkKSAlPiUNCiAgc3VtbWFyaXplKA0KICAgIG1pbl9hc3NheV90ZW1wX2RpZmYgPSBtaW4oYXNzYXlfdGVtcF9kaWZmKSwNCiAgICBtYXhfYXNzYXlfdGVtcF9kaWZmID0gbWF4KGFzc2F5X3RlbXBfZGlmZikNCiAgKQ0KDQojIFJlbmFtZSB2YXJpYWJsZSBsZXZlbHMNCmVtbWVhbnNfZnVsbF9tb2RlbF9hc3NheSR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX2Z1bGxfbW9kZWxfYXNzYXkkdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KZW1tZWFuc19mdWxsX21vZGVsX2Fzc2F5JHdhcm1fY29sZCA8LSBmYWN0b3IoZW1tZWFuc19mdWxsX21vZGVsX2Fzc2F5JHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgVGFpbG9yIHByZWRpY3Rpb25zIHRvIHRoZSByYW5nZSBvZiB0aGUgZGF0YQ0KZW1tZWFuc19mdWxsX21vZGVsX2Fzc2F5IDwtIGVtbWVhbnNfZnVsbF9tb2RlbF9hc3NheSAlPiUNCiAgbGVmdF9qb2luKHJhbmdlX2RmLCBieSA9IGMoInRyYWl0X3R5cGUiLCAid2FybV9jb2xkIikpICU+JQ0KICBmaWx0ZXIoDQogICAgYXNzYXlfdGVtcF9kaWZmID49IG1pbl9hc3NheV90ZW1wX2RpZmYsDQogICAgYXNzYXlfdGVtcF9kaWZmIDw9IG1heF9hc3NheV90ZW1wX2RpZmYNCiAgKQ0KDQoNCiMgUGxvdA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArICANCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCAjIFZlcnRpY2FsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSkgKyANCiAgICBnZW9tX3BvaW50KGRhdGEgPSBkYXRhLCAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBhc3NheV90ZW1wX2RpZmYsIA0KICAgICAgICAgICAgICAgICAgICAgIHkgPSBsbkNWUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5DVlIpLCANCiAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgICBzaGFwZSA9IDIxLCANCiAgICAgICAgICAgICAgICAgIGFscGhhID0gMC43LCANCiAgICAgICAgICAgICAgICAgIHN0cm9rZSA9IDEsDQogICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IDAuMDUpKSArIA0KICAgICBnZW9tX3JpYmJvbihkYXRhID0gZW1tZWFuc19mdWxsX21vZGVsX2Fzc2F5LCAjIFNoYWRlZCBhcmVhIGZvciBjcmVkaWJsZSBpbnRlcnZhbHMNCiAgICAgICAgICAgICAgICAgYWVzKHggPSBhc3NheV90ZW1wX2RpZmYsDQogICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgIGFscGhhID0gLjUpICsgDQogICAgIGdlb21fbGluZShkYXRhID0gZW1tZWFuc19mdWxsX21vZGVsX2Fzc2F5LCAgIyBQcmVkaWN0ZWQgcmVncmVzc2lvbiBsaW5lDQogICAgICAgICAgICAgICBhZXMoeSA9IGVtbWVhbiwNCiAgICAgICAgICAgICAgICAgICB4ID0gYXNzYXlfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArIA0KICANCiAgICBnZW9tX3RleHQoZGF0YSA9IHNhbXBsZV9zaXplcywgDQogICAgICAgICAgICAgIGFlcyh4ID0gSW5mLCANCiAgICAgICAgICAgICAgICAgIHkgPSBpZmVsc2Uod2FybV9jb2xkID09ICJXYXJtIiwgLTIsIC0yLjc1KSwgICMgU2FtcGxlIHNpemVzDQogICAgICAgICAgICAgICAgICBsYWJlbCA9IHBhc3RlMCgiayA9ICIsIGVzdGltYXRlcywgIiAoIiwgc3R1ZGllcywgIikiKSwNCiAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgIGhqdXN0ID0gMS4wNSwgc2l6ZSA9IDUsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgDQogIGZhY2V0X3dyYXAofiB0cmFpdF90eXBlLCBuY29sID0gMSkgKyAjIERpZmZlcmVudCBwYW5lbHMgZm9yIGVhY2ggdHJhaXQNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICBsYWJzKHggPSAiQXNzYXkgdGVtcGVyYXR1cmUgZGlmZmVyZW5jZSIsIHkgPSAibG5DVlIiLA0KICAgICAgIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCA4KSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNSwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIyKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTMsIDMpKQ0KDQpnZ3NhdmUoZmlsZSA9ICJmaWcvbG5DVlJfYWxsX21vZGVyYXRvcnNfYXNzYXlfdGVtcF9kaWZmLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDEwLCBkcGkgPSA1MDApDQpgYGANCg0KDQojIyAqKkNoYW5nZXMgaW4gdHJhaXQgdmFyaWFuY2UgKGxuVlIpKiogey50YWJzZXQgLnRhYnNldF9mYWRlIC50YWJzZXRfcGlsbHN9DQoNCiMjIyAqKk92ZXJhbGwgbW9kZWwqKg0KDQojIyMjICpNb2RlbCBzcGVjaWZpY2F0aW9uKg0KYGBge3IsIGV2YWwgPSBGfQ0KIyBNb2RlbCBzcGVjaWZpY2F0aW9uDQpmb3JtdWxhIDwtIGJmKGxuVlIgfiB0cmFpdF90eXBlIC0xICsgIyBTZXBhcmF0ZSBlZmZlY3RzIGJ5IHRyYWl0IHR5cGUNCiAgICAgICAgICAgICAgICAodHJhaXRfdHlwZS0xfHJlZikgKyAjIENvcnJlbGF0aW9uIGJldHdlZW4gdHJhaXRzIGFtb25nIHN0dWRpZXMNCiAgICAgICAgICAgICAgICAoMXxzcGVjaWVzKSArICMgU3BlY2llcy1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8Z3IocGh5bG9nZW55LCBjb3YgPSBwaHlsb19tYXRyaXgpKSArICMgUGh5bG9nZW5ldGljIHJlbGF0ZWRuZXNzDQogICAgICAgICAgICAgICAgKDF8ZXhwZXJpbWVudF9JRCkgKyAjIEV4cGVyaW1lbnQtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfG9icykgKyAjIE9ic2VydmF0aW9uLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICBmY29yKFZDVl9sblZSKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5WUl9tb2RlbF9vdmVyYWxsIDwtIGJybShmb3JtdWxhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IGdhdXNzaWFuKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhMiA9IGxpc3QocGh5bG9fbWF0cml4ID0gcGh5bG9fbWF0cml4LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZDVl9sblZSID0gVkNWX2xuVlIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IgPSBwcmlvciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OSwgbWF4X3RyZWVkZXB0aCA9IDE1KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXIgPSA0MDAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm11cCA9IDIwMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFpbnMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gMTIzKSANCg0KIyBTYXZlIG1vZGVsDQpzYXZlUkRTKGxuVlJfbW9kZWxfb3ZlcmFsbCwgZmlsZSA9ICJSRGF0YS9sblZSX21vZGVsX292ZXJhbGwucmRzIikNCmBgYA0KDQojIyMjICpNb2RlbCBvdXRwdXQqDQpgYGB7cn0NCiMgTG9hZCBtb2RlbA0KbG5WUl9tb2RlbF9vdmVyYWxsIDwtIHJlYWRSRFMoIlJEYXRhL2xuVlJfbW9kZWxfb3ZlcmFsbC5yZHMiKQ0KDQojIERpc3BsYXkgbW9kZWwgb3V0cHV0IA0Kc3VtbWFyeShsblZSX21vZGVsX292ZXJhbGwpDQoNCiMgQ2xlYW5lZCBtb2RlbCBvdXRwdXQNCmFzLmRhdGEuZnJhbWUoZml4ZWYobG5WUl9tb2RlbF9vdmVyYWxsLCBzdW1tYXJ5ID0gVFJVRSkpICU+JQ0KICAjIFJlbmFtZSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgZm9yIGNsZWFuZXIgZGlzcGxheQ0KICByb3duYW1lc190b19jb2x1bW4odmFyID0gIlBhcmFtZXRlciIpICU+JSANCiAgbXV0YXRlKA0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKykiLCAiXFwxIiwgUGFyYW1ldGVyKQ0KICApICU+JQ0KICAjIFJvdW5kIG51bWJlcnMgdG8gMyBkZWNpbWFsIHBvaW50cw0KICBtdXRhdGUoYWNyb3NzKGMoRXN0aW1hdGUsIFEyLjUsIFE5Ny41KSwgfiByb3VuZCguLCAzKSkpICU+JQ0KICBzZWxlY3QoUGFyYW1ldGVyLCBFc3RpbWF0ZSwgYExvd2VyIENJYCA9IFEyLjUsIGBVcHBlciBDSWAgPSBROTcuNSkgJT4lDQogIGthYmxlKCkgJT4lDQogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBwb3NpdGlvbiA9ICJjZW50ZXIiLCBmaXhlZF90aGVhZCA9IFRSVUUpICU+JQ0KICBjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSwgYm9yZGVyX3JpZ2h0ID0gVFJVRSkgJT4lDQogIHJvd19zcGVjKDAsIGJhY2tncm91bmQgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIsIGJvbGQgPSBUUlVFKSAlPiUNCiAga2FibGVfc3R5bGluZyhmaXhlZF90aGVhZCA9IFRSVUUpDQpgYGANCg0KIyMjIyAqSGV0ZXJvZ2VuZWl0eSBhbmFseXNpcyoNCmBgYHtyfQ0KIyBFeHRyYWN0aW5nIHRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uIGZyb20gdGhlIG1vZGVsDQpwb3N0ZXJpb3IgPC0gcG9zdGVyaW9yX3NhbXBsZXMobG5WUl9tb2RlbF9vdmVyYWxsKQ0KDQojIENhbGN1bGF0ZSBtZWFzdXJlbWVudCBlcnJvciB2YXJpYW5jZQ0Kc2lnbWEyX3YgPC0gc3VtKDEvZGlhZyhWQ1ZfbG5WUikpICogKGxlbmd0aChkaWFnKFZDVl9sblZSKSktIDEpLyhzdW0oMS9kaWFnKFZDVl9sblZSKSleMiAtIHN1bSgoMS9kaWFnKFZDVl9sblZSKSleMikpDQoNCiMgQ2FsY3VsYXRlIHRoZSB0b3RhbCB2YXJpYW5jZSAoaW5jbHVkaW5nIHRoZSBtZWFzdXJlbWVudCBlcnJvciB2YXJpYW5jZSkNCnZhcl90b3RhbCA8LSBwb3N0ZXJpb3Ikc2RfZXhwZXJpbWVudF9JRF9fSW50ZXJjZXB0ICsNCiAgICAgICAgICAgICBwb3N0ZXJpb3Ikc2Rfb2JzX19JbnRlcmNlcHQgKw0KICAgICAgICAgICAgIHBvc3RlcmlvciRzZF9waHlsb2dlbnlfX0ludGVyY2VwdCArDQogICAgICAgICAgICAgcG9zdGVyaW9yJHNkX3JlZl9fdHJhaXRfdHlwZWJvZHlfc2l6ZSArDQogICAgICAgICAgICAgcG9zdGVyaW9yJHNkX3JlZl9fdHJhaXRfdHlwZWZlY3VuZGl0eSArDQogICAgICAgICAgICAgcG9zdGVyaW9yJHNkX3JlZl9fdHJhaXRfdHlwZXN1cnZpdmFsICsNCiAgICAgICAgICAgICBwb3N0ZXJpb3Ikc2Rfc3BlY2llc19fSW50ZXJjZXB0ICsNCiAgICAgICAgICAgICBzaWdtYTJfdg0KDQojIENhbGN1bGF0ZSBoZXRlcm9nZW5laXR5IChJMikNCkkyIDwtIGxpc3QoDQogICAgSTJfdG90YWwgPSAodmFyX3RvdGFsIC0gc2lnbWEyX3YpIC8gdmFyX3RvdGFsLCAjIFRvdGFsIGhldGVyb2dlbmVpdHkNCiAgICBJMl9zdHVkeSA9IChwb3N0ZXJpb3Ikc2RfcmVmX190cmFpdF90eXBlYm9keV9zaXplICsgIyBIZXRlcm9nZW5laXR5IGV4cGxhaW5lZCBieSBzdHVkeSBkaWZmZXJlbmNlcw0KICAgICAgICAgICAgICAgIHBvc3RlcmlvciRzZF9yZWZfX3RyYWl0X3R5cGVmZWN1bmRpdHkgKw0KICAgICAgICAgICAgICAgIHBvc3RlcmlvciRzZF9yZWZfX3RyYWl0X3R5cGVzdXJ2aXZhbCkgLyB2YXJfdG90YWwsDQogICAgSTJfZXhwID0gcG9zdGVyaW9yJHNkX2V4cGVyaW1lbnRfSURfX0ludGVyY2VwdCAvIHZhcl90b3RhbCwgIyBIZXRlcm9nZW5laXR5IGV4cGxhaW5lZCBieSBleHBlcmltZW50IGRpZmZlcmVuY2VzDQogICAgSTJfc3AgPSBwb3N0ZXJpb3Ikc2Rfc3BlY2llc19fSW50ZXJjZXB0IC8gdmFyX3RvdGFsLCAjIEhldGVyb2dlbmVpdHkgZXhwbGFpbmVkIGJ5IHNwZWNpZXMgZGlmZmVyZW5jZXMNCiAgICBJMl9waHlsbyA9IHBvc3RlcmlvciRzZF9waHlsb2dlbnlfX0ludGVyY2VwdCAvIHZhcl90b3RhbCwgIyBIZXRlcm9nZW5laXR5IGV4cGxhaW5lZCBieSBwaHlsb2dlbmV0aWMgcmVsYXRlZG5lc3MNCiAgICBJMl9vYnMgPSBwb3N0ZXJpb3Ikc2Rfb2JzX19JbnRlcmNlcHQgLyB2YXJfdG90YWwgIyBIZXRlcm9nZW5laXR5IGV4cGxhaW5lZCBieSByZXNpZHVhbCB2YXJpYXRpb24NCg0KKQ0KDQojIENhbGN1bGF0ZSBtZWFuIGFuZCBjcmVkaWJsZSBpbnRlcnZhbHMgDQpzdW1tYXJ5X3RhYmxlIDwtIHQoc2FwcGx5KEkyLCBmdW5jdGlvbih4KSB7DQogICAgYyhNZWFuID0gMTAwKnJvdW5kKG1lYW4oeCksNCksIA0KICAgICAgYCBgID0gMTAwKiByb3VuZChxdWFudGlsZSh4LCAwLjAyNSksNCksIA0KICAgICAgYCBgID0gMTAwKnJvdW5kKHF1YW50aWxlKHgsIDAuOTc1KSw0KSkNCn0pKQ0KDQojIEN1c3RvbWlzZSB0YWJsZQ0Kc3VtbWFyeV90YWJsZSA8LSBzdW1tYXJ5X3RhYmxlICU+JQ0KICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogICAgcm93bmFtZXNfdG9fY29sdW1uKCJWYXJpYWJsZSIpICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgICAgVmFyaWFibGUgPSByZWNvZGUoVmFyaWFibGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJJMl90b3RhbCIgID0gIlRvdGFsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkkyX3N0dWR5IiAgPSAiU3R1ZHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAiSTJfZXhwIiAgICA9ICJFeHBlcmltZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIkkyX3NwIiAgICAgPSAiU3BlY2llcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJJMl9waHlsbyIgID0gIlBoeWxvZ2VueSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICJJMl9vYnMiICAgID0gIlJlc2lkdWFsIikNCiAgICApICU+JQ0KICAgIHJlbmFtZSgNCiAgICAgICAgbG93ZXJfSFBEID0gYCAuMi41JWAsDQogICAgICAgIHVwcGVyX0hQRCA9IGAgLjk3LjUlYA0KICAgICkgJT4lDQogIG11dGF0ZSgNCiAgICBWYXJpYWJsZSA9IHBhc3RlMCgiSTxzdXA+Mjwvc3VwPjxzdWI+IiwgVmFyaWFibGUpICAgIyBDcmVhdGUgYSBuZXcgY29sdW1uIHdpdGggZm9ybWF0dGVkIEnCsiBhbmQgc3Vic2NyaXB0cw0KICApDQoNCg0KIyBEaXNwbGF5IHRhYmxlDQprYWJsZShzdW1tYXJ5X3RhYmxlLCAiaHRtbCIsIGVzY2FwZSA9IEZBTFNFLCANCiAgICAgIGNvbC5uYW1lcyA9IGMoIkhldGVyb2dlbmVpdHkgKCUpIiwgIk1lYW4iLCAiTG93ZXIgSFBEIiwgIlVwcGVyIEhQRCIpLA0KICAgICAgYWxpZ24gPSBjKCdsJywgJ3InLCAncicsICdyJykpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgd2lkdGggPSAiMjAwcHgiLCBib2xkID0gVFJVRSwgYm9yZGVyX3JpZ2h0ID0gVFJVRSkgJT4lDQogIHJvd19zcGVjKDAsIGJhY2tncm91bmQgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIsIGJvbGQgPSBUUlVFKSAlPiUNCiAga2FibGVfc3R5bGluZyhmaXhlZF90aGVhZCA9IFRSVUUpDQoNCmBgYA0KDQojIyMjICpEYXRhIHZpc3VhbGlzYXRpb24qDQpgYGB7ciwgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQ9N30NCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbWVhbnNfb3ZlcmFsbCA8LSBhcy5kYXRhLmZyYW1lKGVtbWVhbnMobG5WUl9tb2RlbF9vdmVyYWxsLCB+IHRyYWl0X3R5cGUpKQ0KDQplbW1lYW5zX292ZXJhbGwkdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19vdmVyYWxsJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQojIFBsb3QNCmdncGxvdCgpICsNCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1LCANCiAgICAgICAgICAgICAgIGx3ZD0xKSArDQogICAgZ2VvbV9xdWFzaXJhbmRvbShkYXRhID0gZGF0YSwgIyBQbG90IGVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5WUiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5WUikpLCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSAiZ3JheTc1IiwNCiAgICAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsDQogICAgICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMjUsIA0KICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjIpICsNCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBlbW1lYW5zX292ZXJhbGwsICAgIyBQbG90IHRoZSBwb2ludCBlc3RpbWF0ZXMgaW4gd2hpdGUgZm9yIGJhY2tncm91bmQNCiAgICAgICAgICAgICAgICAgIGFlcyh5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELA0KICAgICAgICAgICAgICAgICAgICAgIHggPSB0cmFpdF90eXBlKSwgDQogICAgICAgICAgICAgICAgICBzaXplID0gMiwNCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4wODUsDQogICAgICAgICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgICBnZW9tX3BvaW50KGRhdGEgPSBlbW1lYW5zX292ZXJhbGwsICMgUGxvdCB0aGUgY3JlZGlibGUgaW50ZXJ2YWxzIGluIHdoaXRlIGZvciBiYWNrZ3JvdW5kDQogICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgIHkgPSBlbW1lYW4pLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDQuNSwgDQogICAgICAgICAgICAgICBzdHJva2UgPSAxLjUsDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLA0KICAgICAgICAgICAgICAgY29sb3I9IndoaXRlIiwNCiAgICAgICAgICAgICAgIGZpbGwgPSAid2hpdGUiKSArDQogICAgZ2VvbV9lcnJvcmJhcihkYXRhID0gZW1tZWFuc19vdmVyYWxsLCAgIyBQbG90IHRoZSBwb2ludCBlc3RpbWF0ZXMgDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQpLCANCiAgICAgICAgICAgICAgICAgIHNpemUgPSAxLjUsDQogICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMDc1LA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gZW1tZWFuc19vdmVyYWxsLCAjIFBsb3QgdGhlIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICB5ID0gZW1tZWFuKSwNCiAgICAgICAgICAgICAgIHNpemUgPSA0LA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgIHN0cm9rZSA9IDEuNSwNCiAgICAgICAgICAgICAgIGNvbG9yPSJibGFjayIsDQogICAgICAgICAgICAgICBmaWxsID0gIndoaXRlIikgKw0KICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzX3RyYWl0cywgICMgU2FtcGxlIHNpemUgYW5ub3RhdGlvbnMgDQogICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICB5ID0gMy41LA0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIikpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICAgIHRoZW1lX2J3KCkgKyAgICAgIyBDdXN0b21pemUgdGhlIHBsb3QNCiAgICBsYWJzKHkgPSAibG5WUiIsIHggPSAiIikgKw0KICAgIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgOCkpKyANCiAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTQpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuNSkpICsNCiAgICBndWlkZXMoY29sb3IgPSAibm9uZSIsIHNpemUgPSAibm9uZSIpKw0KICAgIGNvb3JkX2ZsaXAoKSArIA0KICAgIHlsaW0oLTMuNSwgMy41KQ0KDQojIFNhdmUgZmlndXJlDQpnZ3NhdmUoZmlsZSA9ICJmaWcvbG5WUl9vdmVyYWxsLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIGRwaSA9IDUwMCkNCmBgYA0KDQojIyMgKipUZW1wZXJhdHVyZSByZWdpbWUqKiANCg0KIyMjIyAqTW9kZWwgc3BlY2lmaWNhdGlvbioNCmBgYHtyLCBldmFsID0gRn0NCiMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KZm9ybXVsYSA8LSBiZihsblZSIH4gdHJhaXRfdHlwZTp3YXJtX2NvbGQgLTEgKyAjIFNlcGFyYXRlIGVmZmVjdHMgYnkgdHJhaXQgdHlwZQ0KICAgICAgICAgICAgICAgICh0cmFpdF90eXBlLTF8cmVmKSArICMgQ29ycmVsYXRpb24gYmV0d2VlbiB0cmFpdHMgYW1vbmcgc3R1ZGllcw0KICAgICAgICAgICAgICAgICgxfHNwZWNpZXMpICsgIyBTcGVjaWVzLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxncihwaHlsb2dlbnksIGNvdiA9IHBoeWxvX21hdHJpeCkpICsgIyBQaHlsb2dlbmV0aWMgcmVsYXRlZG5lc3MNCiAgICAgICAgICAgICAgICAoMXxleHBlcmltZW50X0lEKSArICMgRXhwZXJpbWVudC1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8b2JzKSArICMgT2JzZXJ2YXRpb24tbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgIGZjb3IoVkNWX2xuVlIpKSAjIFZhcmlhbmNlIGNvdmFyaWFuY2UgbWF0aXggb2YgY29ycmVsYXRlZCBzYW1wbGluZyB2YXJpYW5jZXMNCg0KIyBEZWZpbmUgcHJpb3JzDQpwcmlvciA9IGMoDQogIHByaW9yKGNvbnN0YW50KDEpLCBjbGFzcyA9ICJzaWdtYSIpDQopICMgQmVjYXVzZSB0aGUgcmVzaWR1YWwgdmFyaWFuY2UtY292YXJpYW5jZSBzdHJ1Y3R1cmUgaXMgc3BlY2lmaWVkIGluIGZjb3IsIHRoZXJlIGlzIG5vIG5lZWQgdG8gZXN0aW1hdGUgc2lnbWEgc28gaXQgaXMgbGVmdCBhcyBhIGNvbnN0YW50DQoNCiMgRml0IG1vZGVsDQpsblZSX21vZGVsX3dhcm1fY29sZCA8LSBicm0oZm9ybXVsYSwgDQogICAgICAgICAgICAgICAgICBmYW1pbHkgPSBnYXVzc2lhbigpLA0KICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsIA0KICAgICAgICAgICAgICAgICAgZGF0YTIgPSBsaXN0KHBoeWxvX21hdHJpeCA9IHBoeWxvX21hdHJpeCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWQ1ZfbG5WUiA9IFZDVl9sblZSKSwNCiAgICAgICAgICAgICAgICAgIHByaW9yID0gcHJpb3IsDQogICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxNSksDQogICAgICAgICAgICAgICAgICBpdGVyID0gNDAwMCwgDQogICAgICAgICAgICAgICAgICB3YXJtdXAgPSAyMDAwLA0KICAgICAgICAgICAgICAgICAgY2hhaW5zID0gNCwgDQogICAgICAgICAgICAgICAgICBjb3JlcyA9IDQsIA0KICAgICAgICAgICAgICAgICAgc2VlZCA9IDEyMykgDQoNCiMgU2F2ZSBtb2RlbA0Kc2F2ZVJEUyhsblZSX21vZGVsX3dhcm1fY29sZCwgZmlsZSA9ICJSRGF0YS9sblZSX21vZGVsX3dhcm1fY29sZC5yZHMiKQ0KYGBgDQoNCiMjIyMgKk1vZGVsIG91dHB1dCoNCmBgYHtyfQ0KIyBMb2FkIG1vZGVsDQpsblZSX21vZGVsX3dhcm1fY29sZCA8LSByZWFkUkRTKCJSRGF0YS9sblZSX21vZGVsX3dhcm1fY29sZC5yZHMiKQ0KDQojIERpc3BsYXkgbW9kZWwgb3V0cHV0IA0Kc3VtbWFyeShsblZSX21vZGVsX3dhcm1fY29sZCkNCg0KIyBDbGVhbmVkIG1vZGVsIG91dHB1dA0KYXMuZGF0YS5mcmFtZShmaXhlZihsblZSX21vZGVsX3dhcm1fY29sZCwgc3VtbWFyeSA9IFRSVUUpKSAlPiUNCiAgIyBSZW5hbWUgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGZvciBjbGVhbmVyIGRpc3BsYXkNCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJQYXJhbWV0ZXIiKSAlPiUgDQogIG11dGF0ZSgNCiAgICAjIFNpbXBsaWZ5IGB0cmFpdF90eXBlYCBhbmQgYHdhcm1fY29sZGAgaW50ZXJhY3Rpb25zDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKTp3YXJtX2NvbGQoY29sZHx3YXJtKSIsICJcXDEoXFwyKSIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkNvbnRyYXN0cyogDQpgYGB7cn0NCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbXMgPC0gZW1tZWFucyhsblZSX21vZGVsX3dhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgc3BlY3MgPSB+IHdhcm1fY29sZCB8IHRyYWl0X3R5cGUpDQoNCiMgR2VuZXJhdGUgY29udHJhc3RzDQpjb250cmFzdChlbW1zLCBtZXRob2QgPSAicGFpcndpc2UiKQ0KYGBgDQoNCiMjIyMgKkRhdGEgdmlzdWFsaXNhdGlvbioNCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD03fQ0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucw0KZW1tZWFuc193YXJtX2NvbGQgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKGxuVlJfbW9kZWxfd2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGVjcyA9IH4gd2FybV9jb2xkIHwgdHJhaXRfdHlwZSkpDQoNCmVtbWVhbnNfd2FybV9jb2xkJHRyYWl0X3R5cGUgPC0gZmFjdG9yKGVtbWVhbnNfd2FybV9jb2xkJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfd2FybV9jb2xkJHdhcm1fY29sZCA8LSBmYWN0b3IoZW1tZWFuc193YXJtX2NvbGQkd2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiY29sZCIsICJ3YXJtIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJDb2xkIiwgIldhcm0iKSkNCiMgUGxvdA0KZ2dwbG90KCkgKw0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUsIA0KICAgICAgICAgICAgICAgbHdkPTEpICsNCiAgICBnZW9tX3F1YXNpcmFuZG9tKGRhdGEgPSBkYXRhLCAgICAgIyBQbG90IGVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGxuVlIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5WUikpLCANCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsDQogICAgICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMjUsIA0KICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjMpICsNCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBlbW1lYW5zX3dhcm1fY29sZCwgICMgUGxvdCB0aGUgcG9pbnQgZXN0aW1hdGVzIGluIHdoaXRlIGZvciBiYWNrZ3JvdW5kDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBEKSwgDQogICAgICAgICAgICAgICAgICBjb2xvcj0id2hpdGUiLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIuNSwNCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4xNykgKw0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGVtbWVhbnNfd2FybV9jb2xkLCAgIyBQbG90IHRoZSBjcmVkaWJsZSBpbnRlcnZhbHMgaW4gd2hpdGUgZm9yIGJhY2tncm91bmQNCiAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTp3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgIHkgPSBlbW1lYW4pLA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgIHNpemUgPSA0LCANCiAgICAgICAgICAgICAgIHN0cm9rZSA9IDIsDQogICAgICAgICAgICAgICBjb2xvcj0id2hpdGUiLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJ3aGl0ZSIpICsNCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBlbW1lYW5zX3dhcm1fY29sZCwgIyBQbG90IHRoZSBwb2ludCBlc3RpbWF0ZXMgDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBEKSwgDQogICAgICAgICAgICAgICAgICBjb2xvcj0iYmxhY2siLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIsDQogICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMTUpICsNCiAgICBnZW9tX3BvaW50KGRhdGEgPSBlbW1lYW5zX3dhcm1fY29sZCwgIyBQbG90IHRoZSBjcmVkaWJsZSBpbnRlcnZhbHMNCiAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTp3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgIHkgPSBlbW1lYW4pLA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgIHNpemUgPSAzLjUsIA0KICAgICAgICAgICAgICAgc3Ryb2tlID0gMiwNCiAgICAgICAgICAgICAgIGNvbG9yPSJibGFjayIsDQogICAgICAgICAgICAgICBmaWxsID0gIndoaXRlIikgKw0KICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzLCAgIyBTYW1wbGUgc2l6ZSBhbm5vdGF0aW9ucyANCiAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICB5ID0gMy41LA0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogICAgdGhlbWVfYncoKSArICAgICAjIEN1c3RvbWl6ZSB0aGUgcGxvdA0KICAgIGxhYnMoeSA9ICJsblZSIiwgeCA9ICIiKSArDQogICAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCA4KSkrIA0KIyAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjQTVGODIwIiwgIiM3M0I3MDYiLCAgIiM5Q0VGRkMiLCAiIzA2QTJCQSIsICAiI0ZFRDJFRCIsICIjQjkwNjc0IikpKw0KICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIsICIjMDZCNEJBIiwgIiNFODA3NTYiLCAiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNCksDQogICAgICAgICAgYXhpcy50ZXh0LnkgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwLCANCiAgICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCBoanVzdCA9IDAuNSksDQogICAgICAgICAgYXhpcy50ZXh0LnggPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICBjb29yZF9mbGlwKCkgKyANCiAgICB5bGltKC0zLjUsIDMuNSkNCg0KZ2dzYXZlKGZpbGUgPSAiZmlnL2xuVlJfd2FybV9jb2xkLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIGRwaSA9IDUwMCkNCmBgYA0KDQojIyMgKipBc3NheSB0ZW1wZXJhdHVyZSBkaWZmZXJlbmNlKiogDQoNCldlIGNhbGN1bGF0ZWQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgYXNzYXkgdGVtcGVyYXR1cmUgYW5kIGNvbnRyb2wgdGVtcGVyYXR1cmUgKGFzc2F5X3RlbXBfZGlmZikgdG8gYWNjb3VudCBmb3IgdGhlIGZhY3QgdGhhdCBhbmltYWxzIHdlcmUgdGVzdGVkIHRvIGEgZGlmZmVyZW50IHJhbmdlIG9mIHRlbXBlcmF0dXJlcy4gV2UgYWxzbyBwcmVkaWN0ZWQgdGhhdCBlZmZlY3RzIHdpbGwgdmFyeSBpZiB0cmFpdHMgYXJlIGFzc2F5ZWQgYXQgY29sZGVyLSBvciB3YXJtZXItdGhhbi1jb250cm9sIGNvbmRpdGlvbnMsIGRlcGVuZGluZyBvbiB0aGUgdGVtcGVyYXR1cmUgcmVnaW1lLiANCkJlY2F1c2UgdGhlIHZhcmlhdGlvbiBpbiBhc3NheSB0ZW1wZXJhdHVyZSBnZW5lcmF0ZXMgc29tZSBudWlzYW5jZSBoZXRlcm9nZW5laXR5IChzZW5zdSBOb2JsZSBldCBhbC4sIDIwMTcpLCB0aGUgcmVzdWx0cyBvZiBzdWJzZXF1ZW50IG1vZGVscyB3ZXJlIHByb3ZpZGVkIGFmdGVyIGNvbnRyb2xsaW5nIGZvciBhc3NheSB0ZW1wZXJhdHVyZSBkaWZmZXJlbmNlcy4gSW4gb3JkZXIgd29yZHMsIHRoZSByZXN1bHRzIG9mIGFsbCBtb2RlcmF0b3JzIGFyZSBjb25kaXRpb25hbCBvbiBhc3NheSB0ZW1wZXJhdHVyZSwgbWVhbmluZyB0aGF0IHJlc3VsdHMgYXJlIGludGVycHJldGFibGUgYXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBjb250cm9sIGFuZCBzZWxlY3RlZCBsaW5lcywgd2hlbiBhbmltYWxzIGFyZSB0ZXN0ZWQgYXQgdGhlIGNvbnRyb2wgdGVtcGVyYXR1cmUuIA0KDQojIyMjICpNb2RlbCBzcGVjaWZpY2F0aW9uKg0KYGBge3IsIGV2YWwgPSBGfQ0KIyBNb2RlbCBzcGVjaWZpY2F0aW9uDQpmb3JtdWxhIDwtIGJmKGxuVlIgfiAwICsgdHJhaXRfdHlwZTp3YXJtX2NvbGQgKyB0cmFpdF90eXBlOndhcm1fY29sZDphc3NheV90ZW1wX2RpZmYgKyAjIFNlcGFyYXRlIGVmZmVjdHMgYnkgdHJhaXQgdHlwZQ0KICAgICAgICAgICAgICAgICh0cmFpdF90eXBlLTF8cmVmKSArICMgQ29ycmVsYXRpb24gYmV0d2VlbiB0cmFpdHMgYW1vbmcgc3R1ZGllcw0KICAgICAgICAgICAgICAgICgxfHNwZWNpZXMpICsgIyBTcGVjaWVzLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxncihwaHlsb2dlbnksIGNvdiA9IHBoeWxvX21hdHJpeCkpICsgIyBQaHlsb2dlbmV0aWMgcmVsYXRlZG5lc3MNCiAgICAgICAgICAgICAgICAoMXxleHBlcmltZW50X0lEKSArICMgRXhwZXJpbWVudC1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8b2JzKSArICMgT2JzZXJ2YXRpb24tbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgIGZjb3IoVkNWX2xuVlIpKSAjIFZhcmlhbmNlIGNvdmFyaWFuY2UgbWF0aXggb2YgY29ycmVsYXRlZCBzYW1wbGluZyB2YXJpYW5jZXMNCg0KIyBEZWZpbmUgcHJpb3JzDQpwcmlvciA9IGMoDQogIHByaW9yKGNvbnN0YW50KDEpLCBjbGFzcyA9ICJzaWdtYSIpDQopICMgQmVjYXVzZSB0aGUgcmVzaWR1YWwgdmFyaWFuY2UtY292YXJpYW5jZSBzdHJ1Y3R1cmUgaXMgc3BlY2lmaWVkIGluIGZjb3IsIHRoZXJlIGlzIG5vIG5lZWQgdG8gZXN0aW1hdGUgc2lnbWEgc28gaXQgaXMgbGVmdCBhcyBhIGNvbnN0YW50DQoNCiMgRml0IG1vZGVsDQpsblZSX21vZGVsX2Fzc2F5X3RlbXBfZGlmZiA8LSBicm0oZm9ybXVsYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gZ2F1c3NpYW4oKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTIgPSBsaXN0KHBoeWxvX21hdHJpeCA9IHBoeWxvX21hdHJpeCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVkNWX2xuVlIgPSBWQ1ZfbG5WUiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IgPSBwcmlvciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDQwMDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm11cCA9IDIwMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhaW5zID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gMTIzKSANCg0KIyBTYXZlIG1vZGVsDQpzYXZlUkRTKGxuVlJfbW9kZWxfYXNzYXlfdGVtcF9kaWZmLCBmaWxlID0gIlJEYXRhL2xuVlJfbW9kZWxfYXNzYXlfdGVtcF9kaWZmLnJkcyIpDQpgYGANCg0KIyMjIyAqTW9kZWwgb3V0cHV0Kg0KYGBge3J9DQojIExvYWQgbW9kZWwNCmxuVlJfbW9kZWxfYXNzYXlfdGVtcF9kaWZmIDwtIHJlYWRSRFMoIlJEYXRhL2xuVlJfbW9kZWxfYXNzYXlfdGVtcF9kaWZmLnJkcyIpDQoNCiMgRGlzcGxheSBtb2RlbCBvdXRwdXQgDQpzdW1tYXJ5KGxuVlJfbW9kZWxfYXNzYXlfdGVtcF9kaWZmKQ0KDQojIENsZWFuZWQgbW9kZWwgb3V0cHV0DQphcy5kYXRhLmZyYW1lKGZpeGVmKGxuVlJfbW9kZWxfYXNzYXlfdGVtcF9kaWZmLCBzdW1tYXJ5ID0gVFJVRSkpICU+JQ0KICAjIFJlbmFtZSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgZm9yIGNsZWFuZXIgZGlzcGxheQ0KICByb3duYW1lc190b19jb2x1bW4odmFyID0gIlBhcmFtZXRlciIpICU+JSANCiAgbXV0YXRlKA0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKyk6d2FybV9jb2xkKGNvbGR8d2FybSkiLCAiXFwxKFxcMikiLCBQYXJhbWV0ZXIpLA0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKylcXCh3YXJtXFwpOmFzc2F5X3RlbXBfZGlmZiIsICJcXDEod2FybSk6IGFzc2F5X3RlbXBfZGlmZiIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkRhdGEgdmlzdWFsaXNhdGlvbioNCg0KYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0PTEwfQ0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucw0KZW1tZWFuc19hc3NheV90ZW1wX2RpZmYgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsblZSX21vZGVsX2Fzc2F5X3RlbXBfZGlmZiwNCiAgc3BlY3MgPSB+IGFzc2F5X3RlbXBfZGlmZiB8IHRyYWl0X3R5cGUgKiB3YXJtX2NvbGQsDQogIGF0ID0gbGlzdChhc3NheV90ZW1wX2RpZmYgPSBzZXEobWluKGRhdGEkYXNzYXlfdGVtcF9kaWZmKSwgbWF4KGRhdGEkYXNzYXlfdGVtcF9kaWZmKSwgYnkgPSAwLjUpKSkNCiAgKQ0KDQojIENhbGN1bGF0ZSByYW5nZSBvZiB2YWx1ZXMgZm9yIGVhY2ggY2F0ZWdvcnkNCnJhbmdlX2RmIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtaW5fYXNzYXlfdGVtcF9kaWZmID0gbWluKGFzc2F5X3RlbXBfZGlmZiksDQogICAgbWF4X2Fzc2F5X3RlbXBfZGlmZiA9IG1heChhc3NheV90ZW1wX2RpZmYpDQogICkNCg0KZW1tZWFuc19hc3NheV90ZW1wX2RpZmYkdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19hc3NheV90ZW1wX2RpZmYkdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KZW1tZWFuc19hc3NheV90ZW1wX2RpZmYkd2FybV9jb2xkIDwtIGZhY3RvcihlbW1lYW5zX2Fzc2F5X3RlbXBfZGlmZiR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KDQojIFRhaWxvciBwcmVkaWN0aW9ucyB0byB0aGUgcmFuZ2Ugb2YgdGhlIGRhdGENCmVtbWVhbnNfYXNzYXlfdGVtcF9kaWZmIDwtIGVtbWVhbnNfYXNzYXlfdGVtcF9kaWZmICU+JQ0KICBsZWZ0X2pvaW4ocmFuZ2VfZGYsIGJ5ID0gYygidHJhaXRfdHlwZSIsICJ3YXJtX2NvbGQiKSkgJT4lDQogIGZpbHRlcigNCiAgICBhc3NheV90ZW1wX2RpZmYgPj0gbWluX2Fzc2F5X3RlbXBfZGlmZiwNCiAgICBhc3NheV90ZW1wX2RpZmYgPD0gbWF4X2Fzc2F5X3RlbXBfZGlmZg0KICApDQoNCiMgUGxvdA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArICANCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCAjIFZlcnRpY2FsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSkgKyANCiAgICBnZW9tX3BvaW50KGRhdGEgPSBkYXRhLCAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBhc3NheV90ZW1wX2RpZmYsIA0KICAgICAgICAgICAgICAgICAgICAgIHkgPSBsblZSLCANCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMS9zcXJ0KHZhcl9sblZSKSwgDQogICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwgDQogICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNywgDQogICAgICAgICAgICAgICAgICBzdHJva2UgPSAxLA0KICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjA1KSkgKyANCiAgICAgZ2VvbV9yaWJib24oZGF0YSA9IGVtbWVhbnNfYXNzYXlfdGVtcF9kaWZmLCAjIFNoYWRlZCBhcmVhIGZvciBjcmVkaWJsZSBpbnRlcnZhbHMNCiAgICAgICAgICAgICAgICAgYWVzKHggPSBhc3NheV90ZW1wX2RpZmYsDQogICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgIGFscGhhID0gLjUpICsgDQogICAgIGdlb21fbGluZShkYXRhID0gZW1tZWFuc19hc3NheV90ZW1wX2RpZmYsICAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSBhc3NheV90ZW1wX2RpZmYsDQogICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsgDQogICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXMsIA0KICAgICAgICAgICAgICBhZXMoeCA9IEluZiwgDQogICAgICAgICAgICAgICAgICB5ID0gaWZlbHNlKHdhcm1fY29sZCA9PSAiV2FybSIsIC0yLCAtMi43NSksICAjIFNhbXBsZSBzaXplcw0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEuMDUsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIA0KICBmYWNldF93cmFwKH4gdHJhaXRfdHlwZSwgbmNvbCA9IDEpICsgIyBEaWZmZXJlbnQgcGFuZWxzIGZvciBlYWNoIHRyYWl0DQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgbGFicyh4ID0gIkFzc2F5IHRlbXBlcmF0dXJlIGRpZmZlcmVuY2UiLCB5ID0gImxuVlIiLA0KICAgICAgIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCA4KSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNSwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIyKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTMuNSwgMy41KSkNCg0KZ2dzYXZlKGZpbGUgPSAiZmlnL2xuVlJfYXNzYXlfdGVtcF9kaWZmLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDEwLCBkcGkgPSA1MDApDQpgYGANCg0KIyMjICoqU2VsZWN0aW9uIHRlbXBlcmF0dXJlKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5WUiB+IDAgKyB0cmFpdF90eXBlOndhcm1fY29sZCArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFpdF90eXBlOndhcm1fY29sZDphc3NheV90ZW1wX2RpZmYgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhaXRfdHlwZTp3YXJtX2NvbGQ6c2VsZWN0X3RlbXBfZGlmZiArICMgU2VwYXJhdGUgZWZmZWN0cyBieSB0cmFpdCB0eXBlDQogICAgICAgICAgICAgICAgKHRyYWl0X3R5cGUtMXxyZWYpICsgIyBDb3JyZWxhdGlvbiBiZXR3ZWVuIHRyYWl0cyBhbW9uZyBzdHVkaWVzDQogICAgICAgICAgICAgICAgKDF8c3BlY2llcykgKyAjIFNwZWNpZXMtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfGdyKHBoeWxvZ2VueSwgY292ID0gcGh5bG9fbWF0cml4KSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5WUikpICMgVmFyaWFuY2UgY292YXJpYW5jZSBtYXRpeCBvZiBjb3JyZWxhdGVkIHNhbXBsaW5nIHZhcmlhbmNlcw0KDQojIERlZmluZSBwcmlvcnMNCnByaW9yID0gYygNCiAgcHJpb3IoY29uc3RhbnQoMSksIGNsYXNzID0gInNpZ21hIikNCikgIyBCZWNhdXNlIHRoZSByZXNpZHVhbCB2YXJpYW5jZS1jb3ZhcmlhbmNlIHN0cnVjdHVyZSBpcyBzcGVjaWZpZWQgaW4gZmNvciwgdGhlcmUgaXMgbm8gbmVlZCB0byBlc3RpbWF0ZSBzaWdtYSBzbyBpdCBpcyBsZWZ0IGFzIGEgY29uc3RhbnQNCg0KIyBGaXQgbW9kZWwNCmxuVlJfbW9kZWxfc2VsX3RlbXBfZGlmZiA8LSBicm0oZm9ybXVsYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IGdhdXNzaWFuKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTIgPSBsaXN0KHBoeWxvX21hdHJpeCA9IHBoeWxvX21hdHJpeCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZDVl9sblZSID0gVkNWX2xuVlIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmlvciA9IHByaW9yLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXIgPSA0MDAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FybXVwID0gMjAwMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhaW5zID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZWQgPSAxMjMpIA0KDQojIFNhdmUgbW9kZWwNCnNhdmVSRFMobG5WUl9tb2RlbF9zZWxfdGVtcF9kaWZmLCBmaWxlID0gIlJEYXRhL2xuVlJfbW9kZWxfc2VsX3RlbXBfZGlmZi5yZHMiKQ0KYGBgDQoNCiMjIyMgKk1vZGVsIG91dHB1dCoNCmBgYHtyfQ0KIyBMb2FkIG1vZGVsDQpsblZSX21vZGVsX3NlbF90ZW1wX2RpZmYgPC0gcmVhZFJEUygiUkRhdGEvbG5WUl9tb2RlbF9zZWxfdGVtcF9kaWZmLnJkcyIpDQoNCiMgRGlzcGxheSBtb2RlbCBvdXRwdXQgDQpzdW1tYXJ5KGxuVlJfbW9kZWxfc2VsX3RlbXBfZGlmZikNCg0KIyBDbGVhbmVkIG1vZGVsIG91dHB1dA0KYXMuZGF0YS5mcmFtZShmaXhlZihsblZSX21vZGVsX3NlbF90ZW1wX2RpZmYsIHN1bW1hcnkgPSBUUlVFKSkgJT4lDQogICMgUmVuYW1lIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBmb3IgY2xlYW5lciBkaXNwbGF5DQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAiUGFyYW1ldGVyIikgJT4lIA0KICBtdXRhdGUoDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKTp3YXJtX2NvbGQoY29sZHx3YXJtKSIsICJcXDEoXFwyKSIsIFBhcmFtZXRlciksDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKVxcKHdhcm1cXCk6c2VsZWN0X3RlbXBfZGlmZiIsICJcXDEod2FybSk6IHNlbGVjdF90ZW1wX2RpZmYiLCBQYXJhbWV0ZXIpDQogICkgJT4lDQogICMgUm91bmQgbnVtYmVycyB0byAzIGRlY2ltYWwgcG9pbnRzDQogIG11dGF0ZShhY3Jvc3MoYyhFc3RpbWF0ZSwgUTIuNSwgUTk3LjUpLCB+IHJvdW5kKC4sIDMpKSkgJT4lDQogIHNlbGVjdChQYXJhbWV0ZXIsIEVzdGltYXRlLCBgTG93ZXIgQ0lgID0gUTIuNSwgYFVwcGVyIENJYCA9IFE5Ny41KSAlPiUNCiAga2FibGUoKSAlPiUNCiAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImNlbnRlciIsIGZpeGVkX3RoZWFkID0gVFJVRSkgJT4lDQogIGNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFLCBib3JkZXJfcmlnaHQgPSBUUlVFKSAlPiUNCiAgcm93X3NwZWMoMCwgYmFja2dyb3VuZCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIiwgYm9sZCA9IFRSVUUpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZpeGVkX3RoZWFkID0gVFJVRSkNCmBgYA0KDQojIyMjICpEYXRhIHZpc3VhbGlzYXRpb24qDQoNCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD0xMH0NCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbWVhbnNfc2VsX3RlbXBfZGlmZiA8LSBhcy5kYXRhLmZyYW1lKGVtbWVhbnMoDQogIGxuVlJfbW9kZWxfc2VsX3RlbXBfZGlmZiwNCiAgc3BlY3MgPSB+IHNlbGVjdF90ZW1wX2RpZmYgfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3Qoc2VsZWN0X3RlbXBfZGlmZiA9IHNlcShtaW4oZGF0YSRzZWxlY3RfdGVtcF9kaWZmKSwgbWF4KGRhdGEkc2VsZWN0X3RlbXBfZGlmZiksIGJ5ID0gMC41KSwNCiAgICAgICAgICAgIGFzc2F5X3RlbXBfZGlmZiA9IDApKQ0KICApICMgQ29uZGl0aW9uYWwgZWZmZWN0cyBvbiBhc3NheV90ZW1wX2RpZmYgPSAwDQoNCiMgQ2FsY3VsYXRlIHJhbmdlIG9mIHZhbHVlcyBmb3IgZWFjaCBjYXRlZ29yeQ0KcmFuZ2VfZGYgPC0gZGF0YSAlPiUNCiAgZ3JvdXBfYnkodHJhaXRfdHlwZSwgd2FybV9jb2xkKSAlPiUNCiAgc3VtbWFyaXplKA0KICAgIG1pbl9zZWxlY3RfdGVtcF9kaWZmID0gbWluKHNlbGVjdF90ZW1wX2RpZmYpLA0KICAgIG1heF9zZWxlY3RfdGVtcF9kaWZmID0gbWF4KHNlbGVjdF90ZW1wX2RpZmYpDQogICkNCg0KZW1tZWFuc19zZWxfdGVtcF9kaWZmJHRyYWl0X3R5cGUgPC0gZmFjdG9yKGVtbWVhbnNfc2VsX3RlbXBfZGlmZiR0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYm9keV9zaXplIiwgImZlY3VuZGl0eSIsICJzdXJ2aXZhbCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQm9keSBzaXplIiwgIkZlY3VuZGl0eSIsICJTdXJ2aXZhbCIpKQ0KDQplbW1lYW5zX3NlbF90ZW1wX2RpZmYkd2FybV9jb2xkIDwtIGZhY3RvcihlbW1lYW5zX3NlbF90ZW1wX2RpZmYkd2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiY29sZCIsICJ3YXJtIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJDb2xkIiwgIldhcm0iKSkNCg0KIyBUYWlsb3IgcHJlZGljdGlvbnMgdG8gdGhlIHJhbmdlIG9mIHRoZSBkYXRhDQplbW1lYW5zX3NlbF90ZW1wX2RpZmYgPC0gZW1tZWFuc19zZWxfdGVtcF9kaWZmICU+JQ0KICBsZWZ0X2pvaW4ocmFuZ2VfZGYsIGJ5ID0gYygidHJhaXRfdHlwZSIsICJ3YXJtX2NvbGQiKSkgJT4lDQogIGZpbHRlcigNCiAgICBzZWxlY3RfdGVtcF9kaWZmID49IG1pbl9zZWxlY3RfdGVtcF9kaWZmLA0KICAgIHNlbGVjdF90ZW1wX2RpZmYgPD0gbWF4X3NlbGVjdF90ZW1wX2RpZmYNCiAgKQ0KDQojIFBsb3QNCmdncGxvdCgpICsgDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgIyBIb3Jpem9udGFsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSkgKyANCiAgICBnZW9tX3BvaW50KGRhdGEgPSBkYXRhLCAgIyBFZmZlY3Qgc2l6ZXMsIHNjYWxlZCBieSBwcmVjaXNpb24NCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gc2VsZWN0X3RlbXBfZGlmZiwgDQogICAgICAgICAgICAgICAgICAgICAgeSA9IGxuVlIsIA0KICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxL3NxcnQodmFyX2xuVlIpLCANCiAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgICBzaGFwZSA9IDIxLCANCiAgICAgICAgICAgICAgICAgIGFscGhhID0gMC43LCANCiAgICAgICAgICAgICAgICAgIHN0cm9rZSA9IDEsDQogICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IDAuMDUpKSArIA0KICAgICBnZW9tX3JpYmJvbihkYXRhID0gZW1tZWFuc19zZWxfdGVtcF9kaWZmLCAjIFNoYWRlZCBhcmVhIGZvciBjcmVkaWJsZSBpbnRlcnZhbHMNCiAgICAgICAgICAgICAgICAgYWVzKHggPSBzZWxlY3RfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICBhbHBoYSA9IC41KSArIA0KICAgICBnZW9tX2xpbmUoZGF0YSA9IGVtbWVhbnNfc2VsX3RlbXBfZGlmZiwgIyBQcmVkaWN0ZWQgcmVncmVzc2lvbiBsaW5lDQogICAgICAgICAgICAgICBhZXMoeSA9IGVtbWVhbiwNCiAgICAgICAgICAgICAgICAgICB4ID0gc2VsZWN0X3RlbXBfZGlmZiwNCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKyAgDQogICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzLCANCiAgICAgICAgICAgICAgYWVzKHggPSBJbmYsIA0KICAgICAgICAgICAgICAgICAgeSA9IGlmZWxzZSh3YXJtX2NvbGQgPT0gIldhcm0iLCAtMiwgLTIuNzUpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBmYWNldF93cmFwKH4gdHJhaXRfdHlwZSwgbmNvbCA9IDEpICsgICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJTZWxlY3Rpb24gdGVtcGVyYXR1cmUgZGlmZmVyZW5jZSIsIHkgPSAibG5WUiIsIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCA4KSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNSwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIyKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTMuNSwgMy41KSkNCg0KZ2dzYXZlKGZpbGUgPSAiZmlnL2xuVlJfc2VsX3RlbXBfZGlmZi5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA3LCBkcGkgPSA1MDApDQpgYGANCg0KIyMjICoqTnVtYmVyIG9mIGdlbmVyYXRpb25zIG9mIHNlbGVjdGlvbioqIA0KDQojIyMjICpNb2RlbCBzcGVjaWZpY2F0aW9uKg0KYGBge3IsIGV2YWwgPSBGfQ0KIyBNb2RlbCBzcGVjaWZpY2F0aW9uDQpmb3JtdWxhIDwtIGJmKGxuVlIgfiAwICsgdHJhaXRfdHlwZTp3YXJtX2NvbGQgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhaXRfdHlwZTp3YXJtX2NvbGQ6YXNzYXlfdGVtcF9kaWZmICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOnNjYWxlKGdlbl9zZWxlY3Rpb24pICsgIyBTZXBhcmF0ZSBlZmZlY3RzIGJ5IHRyYWl0IHR5cGUNCiAgICAgICAgICAgICAgICAodHJhaXRfdHlwZS0xfHJlZikgKyAjIENvcnJlbGF0aW9uIGJldHdlZW4gdHJhaXRzIGFtb25nIHN0dWRpZXMNCiAgICAgICAgICAgICAgICAoMXxzcGVjaWVzKSArICMgU3BlY2llcy1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8Z3IocGh5bG9nZW55LCBjb3YgPSBwaHlsb19tYXRyaXgpKSArICMgUGh5bG9nZW5ldGljIHJlbGF0ZWRuZXNzDQogICAgICAgICAgICAgICAgKDF8ZXhwZXJpbWVudF9JRCkgKyAjIEV4cGVyaW1lbnQtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfG9icykgKyAjIE9ic2VydmF0aW9uLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICBmY29yKFZDVl9sblZSKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5WUl9tb2RlbF9nZW5fc2VsZWN0aW9uIDwtIGJybShmb3JtdWxhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gZ2F1c3NpYW4oKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhMiA9IGxpc3QocGh5bG9fbWF0cml4ID0gcGh5bG9fbWF0cml4LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVkNWX2xuVlIgPSBWQ1ZfbG5WUiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yID0gcHJpb3IsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OSwgbWF4X3RyZWVkZXB0aCA9IDE1KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDQwMDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXJtdXAgPSAyMDAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFpbnMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEyMykgDQojIFNhdmUgbW9kZWwNCnNhdmVSRFMobG5WUl9tb2RlbF9nZW5fc2VsZWN0aW9uLCBmaWxlID0gIlJEYXRhL2xuVlJfbW9kZWxfZ2VuX3NlbGVjdGlvbi5yZHMiKQ0KYGBgDQoNCiMjIyMgKk1vZGVsIG91dHB1dCoNCmBgYHtyfQ0KIyBMb2FkIG1vZGVsDQpsblZSX21vZGVsX2dlbl9zZWxlY3Rpb24gPC0gcmVhZFJEUygiUkRhdGEvbG5WUl9tb2RlbF9nZW5fc2VsZWN0aW9uLnJkcyIpDQoNCiMgRGlzcGxheSBtb2RlbCBvdXRwdXQgDQpzdW1tYXJ5KGxuVlJfbW9kZWxfZ2VuX3NlbGVjdGlvbikNCg0KIyBDbGVhbmVkIG1vZGVsIG91dHB1dA0KYXMuZGF0YS5mcmFtZShmaXhlZihsblZSX21vZGVsX2dlbl9zZWxlY3Rpb24sIHN1bW1hcnkgPSBUUlVFKSkgJT4lDQogICMgUmVuYW1lIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBmb3IgY2xlYW5lciBkaXNwbGF5DQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAiUGFyYW1ldGVyIikgJT4lDQogIG11dGF0ZSgNCiAgICAjIFNpbXBsaWZ5IGB0cmFpdF90eXBlYCBhbmQgYHdhcm1fY29sZGAgaW50ZXJhY3Rpb25zDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKTp3YXJtX2NvbGQoY29sZHx3YXJtKSIsICJcXDEoXFwyKSIsIFBhcmFtZXRlciksDQogICAgIyBBZGp1c3QgZm9yIGFzc2F5X3RlbXBfZGlmZg0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKylcXCgoY29sZHx3YXJtKVxcKTphc3NheV90ZW1wX2RpZmYiLCAiXFwxKFxcMik6IGFzc2F5X3RlbXBfZGlmZiIsIFBhcmFtZXRlciksDQogICAgIyBSZW1vdmUgInNjYWxlIiBmcm9tIGdlbl9zZWxlY3Rpb24NCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJzY2FsZWdlbl9zZWxlY3Rpb24iLCAiZ2VuX3NlbGVjdGlvbiIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkRhdGEgdmlzdWFsaXNhdGlvbioNCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD03fQ0KDQojIEdlbmVyYXRlIHByZWRpY3Rpb25zDQplbW1lYW5zX2dlbl9zZWxlY3Rpb24gPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsblZSX21vZGVsX2dlbl9zZWxlY3Rpb24sDQogIHNwZWNzID0gfiBnZW5fc2VsZWN0aW9uIHwgdHJhaXRfdHlwZSAqIHdhcm1fY29sZCwNCiAgYXQgPSBsaXN0KGdlbl9zZWxlY3Rpb24gPSBzZXEobWluKGRhdGEkZ2VuX3NlbGVjdGlvbiksIG1heChkYXRhJGdlbl9zZWxlY3Rpb24pLCBieSA9IDEpLA0KICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID0gMCkpDQogICkgIyBDb25kaXRpb25hbCBlZmZlY3RzIG9uIGFzc2F5X3RlbXBfZGlmZiA9IDANCg0KIyBDYWxjdWxhdGUgcmFuZ2Ugb2YgdmFsdWVzIGZvciBlYWNoIGNhdGVnb3J5DQpyYW5nZV9kZiA8LSBkYXRhICU+JQ0KICBncm91cF9ieSh0cmFpdF90eXBlLCB3YXJtX2NvbGQpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWluX2dlbl9zZWxlY3Rpb24gPSBtaW4oZ2VuX3NlbGVjdGlvbiksDQogICAgbWF4X2dlbl9zZWxlY3Rpb24gPSBtYXgoZ2VuX3NlbGVjdGlvbikNCiAgKQ0KDQplbW1lYW5zX2dlbl9zZWxlY3Rpb24kdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19nZW5fc2VsZWN0aW9uJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfZ2VuX3NlbGVjdGlvbiR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfZ2VuX3NlbGVjdGlvbiR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KDQojIFRhaWxvciBwcmVkaWN0aW9ucyB0byB0aGUgcmFuZ2Ugb2YgdGhlIGRhdGENCmVtbWVhbnNfZ2VuX3NlbGVjdGlvbiA8LSBlbW1lYW5zX2dlbl9zZWxlY3Rpb24gJT4lDQogIGxlZnRfam9pbihyYW5nZV9kZiwgYnkgPSBjKCJ0cmFpdF90eXBlIiwgIndhcm1fY29sZCIpKSAlPiUNCiAgZmlsdGVyKA0KICAgIGdlbl9zZWxlY3Rpb24gPj0gbWluX2dlbl9zZWxlY3Rpb24sDQogICAgZ2VuX3NlbGVjdGlvbiA8PSBtYXhfZ2VuX3NlbGVjdGlvbg0KICApDQoNCiMgUGxvdA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsICAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBnZW5fc2VsZWN0aW9uLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5WUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5WUiksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX2dlbl9zZWxlY3Rpb24sICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IGdlbl9zZWxlY3Rpb24sDQogICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgIGFscGhhID0gLjUpICsgDQogICAgIGdlb21fbGluZShkYXRhID0gZW1tZWFuc19nZW5fc2VsZWN0aW9uLCAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSBnZW5fc2VsZWN0aW9uLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArICANCiAgICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXMsIA0KICAgICAgICAgICAgICBhZXMoeCA9IEluZiwgDQogICAgICAgICAgICAgICAgICB5ID0gaWZlbHNlKHdhcm1fY29sZCA9PSAiV2FybSIsIC0yLCAtMi43NSksICAjIFNhbXBsZSBzaXplcw0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEuMDUsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGZhY2V0X3dyYXAofiB0cmFpdF90eXBlLCBuY29sID0gMSkgKyAgIyBEaWZmZXJlbnQgcGFuZWxzIGZvciBlYWNoIHRyYWl0DQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgbGFicyh4ID0gIk51bWJlciBvZiBnZW5lcmF0aW9ucyBvZiBzZWxlY3Rpb24iLCB5ID0gImxuVlIiLCBjb2wgPSAiUmVnaW1lIikgKw0KICB0aGVtZV9idygpICsgDQogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgOCkpKyANCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjUsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxOCksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAyMikpICsNCiAgICBndWlkZXMoZmlsbCA9ICJub25lIiwgc2l6ZSA9ICJub25lIikrDQogICAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0zLjUsIDMuNSksDQogICAgICAgICAgICAgICAgICAgIHhsaW0gPSBjKDAsIDE1MCkpDQoNCmdnc2F2ZShmaWxlID0gImZpZy9sblZSX2dlbl9zZWxlY3Rpb24ucG5nIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNywgZHBpID0gNTAwKQ0KYGBgDQoNCiMjIyAqKk51bWJlciBvZiBnZW5lcmF0aW9ucyBvZiBjb21tb24gZ2FyZGVuKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5WUiB+IDAgKyB0cmFpdF90eXBlOndhcm1fY29sZCArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFpdF90eXBlOndhcm1fY29sZDphc3NheV90ZW1wX2RpZmYgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhaXRfdHlwZTp3YXJtX2NvbGQ6c2NhbGUoZ2VuX2NvbW1vbl9nYXJkZW4pICsgIyBTZXBhcmF0ZSBlZmZlY3RzIGJ5IHRyYWl0IHR5cGUNCiAgICAgICAgICAgICAgICAodHJhaXRfdHlwZS0xfHJlZikgKyAjIENvcnJlbGF0aW9uIGJldHdlZW4gdHJhaXRzIGFtb25nIHN0dWRpZXMNCiAgICAgICAgICAgICAgICAoMXxzcGVjaWVzKSArICMgU3BlY2llcy1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8Z3IocGh5bG9nZW55LCBjb3YgPSBwaHlsb19tYXRyaXgpKSArICMgUGh5bG9nZW5ldGljIHJlbGF0ZWRuZXNzDQogICAgICAgICAgICAgICAgKDF8ZXhwZXJpbWVudF9JRCkgKyAjIEV4cGVyaW1lbnQtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfG9icykgKyAjIE9ic2VydmF0aW9uLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICBmY29yKFZDVl9sblZSKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5WUl9tb2RlbF9nZW5fY29tbW9uX2dhcmRlbiA8LSBicm0oZm9ybXVsYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IGdhdXNzaWFuKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTIgPSBsaXN0KHBoeWxvX21hdHJpeCA9IHBoeWxvX21hdHJpeCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZDVl9sblZSID0gVkNWX2xuVlIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmlvciA9IHByaW9yLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXIgPSA0MDAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FybXVwID0gMjAwMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhaW5zID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZWQgPSAxMjMpIA0KIyBTYXZlIG1vZGVsDQpzYXZlUkRTKGxuVlJfbW9kZWxfZ2VuX2NvbW1vbl9nYXJkZW4sIGZpbGUgPSAiUkRhdGEvbG5WUl9tb2RlbF9nZW5fY29tbW9uX2dhcmRlbi5yZHMiKQ0KYGBgDQoNCiMjIyMgKk1vZGVsIG91dHB1dCoNCmBgYHtyfQ0KIyBMb2FkIG1vZGVsDQpsblZSX21vZGVsX2dlbl9jb21tb25fZ2FyZGVuIDwtIHJlYWRSRFMoIlJEYXRhL2xuVlJfbW9kZWxfZ2VuX2NvbW1vbl9nYXJkZW4ucmRzIikNCg0KIyBEaXNwbGF5IG1vZGVsIG91dHB1dCANCnN1bW1hcnkobG5WUl9tb2RlbF9nZW5fY29tbW9uX2dhcmRlbikNCg0KIyBDbGVhbmVkIG1vZGVsIG91dHB1dA0KYXMuZGF0YS5mcmFtZShmaXhlZihsblZSX21vZGVsX2dlbl9jb21tb25fZ2FyZGVuLCBzdW1tYXJ5ID0gVFJVRSkpICU+JQ0KICAjIFJlbmFtZSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgZm9yIGNsZWFuZXIgZGlzcGxheQ0KICByb3duYW1lc190b19jb2x1bW4odmFyID0gIlBhcmFtZXRlciIpICU+JQ0KICBtdXRhdGUoDQogICAgIyBTaW1wbGlmeSBgdHJhaXRfdHlwZWAgYW5kIGB3YXJtX2NvbGRgIGludGVyYWN0aW9ucw0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKyk6d2FybV9jb2xkKGNvbGR8d2FybSkiLCAiXFwxKFxcMikiLCBQYXJhbWV0ZXIpLA0KICAgICMgQWRqdXN0IGZvciBhc3NheV90ZW1wX2RpZmYNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspXFwoKGNvbGR8d2FybSlcXCk6YXNzYXlfdGVtcF9kaWZmIiwgIlxcMShcXDIpOiBhc3NheV90ZW1wX2RpZmYiLCBQYXJhbWV0ZXIpLA0KICAgICMgUmVtb3ZlICJzY2FsZSIgZnJvbSBnZW5fc2VsZWN0aW9uDQogICAgUGFyYW1ldGVyID0gZ3N1Yigic2NhbGVnZW5fY29tbW9uX2dhcmRlbiIsICJnZW5fY29tbW9uX2dhcmRlbiIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkRhdGEgdmlzdWFsaXNhdGlvbioNCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD0xMH0NCg0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucw0KZW1tZWFuc19nZW5fY29tbW9uX2dhcmRlbiA8LSBhcy5kYXRhLmZyYW1lKGVtbWVhbnMoDQogIGxuVlJfbW9kZWxfZ2VuX2NvbW1vbl9nYXJkZW4sDQogIHNwZWNzID0gfiBnZW5fY29tbW9uX2dhcmRlbiB8IHRyYWl0X3R5cGUgKiB3YXJtX2NvbGQsDQogIGF0ID0gbGlzdChnZW5fY29tbW9uX2dhcmRlbiA9IHNlcShtaW4oZGF0YSRnZW5fY29tbW9uX2dhcmRlbiksIG1heChkYXRhJGdlbl9jb21tb25fZ2FyZGVuKSwgYnkgPSAxKSwNCiAgICAgICAgICAgIGFzc2F5X3RlbXBfZGlmZiA9IDApKQ0KICApICMgQ29uZGl0aW9uYWwgZWZmZWN0cyBvbiBhc3NheV90ZW1wX2RpZmYgPSAwDQoNCiMgQ2FsY3VsYXRlIHJhbmdlIG9mIHZhbHVlcyBmb3IgZWFjaCBjYXRlZ29yeQ0KcmFuZ2VfZGYgPC0gZGF0YSAlPiUNCiAgZ3JvdXBfYnkodHJhaXRfdHlwZSwgd2FybV9jb2xkKSAlPiUNCiAgc3VtbWFyaXplKA0KICAgIG1pbl9nZW5fY29tbW9uX2dhcmRlbiA9IG1pbihnZW5fY29tbW9uX2dhcmRlbiksDQogICAgbWF4X2dlbl9jb21tb25fZ2FyZGVuID0gbWF4KGdlbl9jb21tb25fZ2FyZGVuKQ0KICApDQoNCmVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4kdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19nZW5fY29tbW9uX2dhcmRlbiR0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYm9keV9zaXplIiwgImZlY3VuZGl0eSIsICJzdXJ2aXZhbCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQm9keSBzaXplIiwgIkZlY3VuZGl0eSIsICJTdXJ2aXZhbCIpKQ0KDQplbW1lYW5zX2dlbl9jb21tb25fZ2FyZGVuJHdhcm1fY29sZCA8LSBmYWN0b3IoZW1tZWFuc19nZW5fY29tbW9uX2dhcmRlbiR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KDQojIFRhaWxvciBwcmVkaWN0aW9ucyB0byB0aGUgcmFuZ2Ugb2YgdGhlIGRhdGENCmVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4gPC0gZW1tZWFuc19nZW5fY29tbW9uX2dhcmRlbiAlPiUNCiAgbGVmdF9qb2luKHJhbmdlX2RmLCBieSA9IGMoInRyYWl0X3R5cGUiLCAid2FybV9jb2xkIikpICU+JQ0KICBmaWx0ZXIoDQogICAgZ2VuX2NvbW1vbl9nYXJkZW4gPj0gbWluX2dlbl9jb21tb25fZ2FyZGVuLA0KICAgIGdlbl9jb21tb25fZ2FyZGVuIDw9IG1heF9nZW5fY29tbW9uX2dhcmRlbg0KICApDQoNCiMgUGxvdA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsICAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBnZW5fY29tbW9uX2dhcmRlbiwgDQogICAgICAgICAgICAgICAgICAgICAgeSA9IGxuVlIsIA0KICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxL3NxcnQodmFyX2xuVlIpLCANCiAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgICBzaGFwZSA9IDIxLCANCiAgICAgICAgICAgICAgICAgIGFscGhhID0gMC43LCANCiAgICAgICAgICAgICAgICAgIHN0cm9rZSA9IDEsDQogICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IDAuMDUpKSArIA0KICAgICBnZW9tX3JpYmJvbihkYXRhID0gZW1tZWFuc19nZW5fY29tbW9uX2dhcmRlbiwgIyBTaGFkZWQgYXJlYSBmb3IgY3JlZGlibGUgaW50ZXJ2YWxzDQogICAgICAgICAgICAgICAgIGFlcyh4ID0gZ2VuX2NvbW1vbl9nYXJkZW4sDQogICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgIGFscGhhID0gLjUpICsgDQogICAgIGdlb21fbGluZShkYXRhID0gZW1tZWFuc19nZW5fY29tbW9uX2dhcmRlbiwgIyBQcmVkaWN0ZWQgcmVncmVzc2lvbiBsaW5lDQogICAgICAgICAgICAgICBhZXMoeSA9IGVtbWVhbiwNCiAgICAgICAgICAgICAgICAgICB4ID0gZ2VuX2NvbW1vbl9nYXJkZW4sDQogICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsgIA0KICAgICBnZW9tX3RleHQoZGF0YSA9IHNhbXBsZV9zaXplcywgDQogICAgICAgICAgICAgIGFlcyh4ID0gSW5mLCANCiAgICAgICAgICAgICAgICAgIHkgPSBpZmVsc2Uod2FybV9jb2xkID09ICJXYXJtIiwgLTIsIC0yLjc1KSwgICMgU2FtcGxlIHNpemVzDQogICAgICAgICAgICAgICAgICBsYWJlbCA9IHBhc3RlMCgiayA9ICIsIGVzdGltYXRlcywgIiAoIiwgc3R1ZGllcywgIikiKSwNCiAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgIGhqdXN0ID0gMS4wNSwgc2l6ZSA9IDUsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgZmFjZXRfd3JhcCh+IHRyYWl0X3R5cGUsIG5jb2wgPSAxKSArICAjIERpZmZlcmVudCBwYW5lbHMgZm9yIGVhY2ggdHJhaXQNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICBsYWJzKHggPSAiTnVtYmVyIG9mIGdlbmVyYXRpb25zIG9mIGNvbW1vbiBnYXJkZW4iLCB5ID0gImxuVlIiLCBjb2wgPSAiUmVnaW1lIikgKw0KICB0aGVtZV9idygpICsgDQogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgOCkpKyANCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjUsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxOCksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAyMikpICsNCiAgICBndWlkZXMoZmlsbCA9ICJub25lIiwgc2l6ZSA9ICJub25lIikrDQogICAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0zLjUsIDMuNSksDQogICAgICAgICAgICAgICAgICAgIHhsaW0gPSBjKDAsIDEyKSkNCg0KZ2dzYXZlKGZpbGUgPSAiZmlnL2xuVlJfZ2VuX2NvbW1vbl9nYXJkZW4ucG5nIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNywgZHBpID0gNTAwKQ0KYGBgDQoNCiMjIyAqKlBvcHVsYXRpb24gc2l6ZSoqIA0KDQojIyMjICpNb2RlbCBzcGVjaWZpY2F0aW9uKg0KYGBge3IsIGV2YWwgPSBGfQ0KIyBNb2RlbCBzcGVjaWZpY2F0aW9uDQpmb3JtdWxhIDwtIGJmKGxuVlIgfiAwICsgdHJhaXRfdHlwZTp3YXJtX2NvbGQgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhaXRfdHlwZTp3YXJtX2NvbGQ6YXNzYXlfdGVtcF9kaWZmICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOnNjYWxlKHBvcF9zaXplKSArICMgU2VwYXJhdGUgZWZmZWN0cyBieSB0cmFpdCB0eXBlDQogICAgICAgICAgICAgICAgKHRyYWl0X3R5cGUtMXxyZWYpICsgIyBDb3JyZWxhdGlvbiBiZXR3ZWVuIHRyYWl0cyBhbW9uZyBzdHVkaWVzDQogICAgICAgICAgICAgICAgKDF8c3BlY2llcykgKyAjIFNwZWNpZXMtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfGdyKHBoeWxvZ2VueSwgY292ID0gcGh5bG9fbWF0cml4KSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5WUikpICMgVmFyaWFuY2UgY292YXJpYW5jZSBtYXRpeCBvZiBjb3JyZWxhdGVkIHNhbXBsaW5nIHZhcmlhbmNlcw0KDQojIERlZmluZSBwcmlvcnMNCnByaW9yID0gYygNCiAgcHJpb3IoY29uc3RhbnQoMSksIGNsYXNzID0gInNpZ21hIikNCikgIyBCZWNhdXNlIHRoZSByZXNpZHVhbCB2YXJpYW5jZS1jb3ZhcmlhbmNlIHN0cnVjdHVyZSBpcyBzcGVjaWZpZWQgaW4gZmNvciwgdGhlcmUgaXMgbm8gbmVlZCB0byBlc3RpbWF0ZSBzaWdtYSBzbyBpdCBpcyBsZWZ0IGFzIGEgY29uc3RhbnQNCg0KIyBGaXQgbW9kZWwNCmxuVlJfbW9kZWxfcG9wX3NpemUgPC0gYnJtKGZvcm11bGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBnYXVzc2lhbigpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEyID0gbGlzdChwaHlsb19tYXRyaXggPSBwaHlsb19tYXRyaXgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWQ1ZfbG5WUiA9IFZDVl9sblZSKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IgPSBwcmlvciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyID0gNDAwMCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm11cCA9IDIwMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYWlucyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JlcyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gMTIzKSANCiMgU2F2ZSBtb2RlbA0Kc2F2ZVJEUyhsblZSX21vZGVsX3BvcF9zaXplLCBmaWxlID0gIlJEYXRhL2xuVlJfbW9kZWxfcG9wX3NpemUucmRzIikNCmBgYA0KDQojIyMjICpNb2RlbCBvdXRwdXQqDQpgYGB7cn0NCiMgTG9hZCBtb2RlbA0KbG5WUl9tb2RlbF9wb3Bfc2l6ZSA8LSByZWFkUkRTKCJSRGF0YS9sblZSX21vZGVsX3BvcF9zaXplLnJkcyIpDQoNCiMgRGlzcGxheSBtb2RlbCBvdXRwdXQgDQpzdW1tYXJ5KGxuVlJfbW9kZWxfcG9wX3NpemUpDQoNCiMgQ2xlYW5lZCBtb2RlbCBvdXRwdXQNCmFzLmRhdGEuZnJhbWUoZml4ZWYobG5WUl9tb2RlbF9wb3Bfc2l6ZSwgc3VtbWFyeSA9IFRSVUUpKSAlPiUNCiAgIyBSZW5hbWUgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGZvciBjbGVhbmVyIGRpc3BsYXkNCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJQYXJhbWV0ZXIiKSAlPiUNCiAgbXV0YXRlKA0KICAgICMgU2ltcGxpZnkgYHRyYWl0X3R5cGVgIGFuZCBgd2FybV9jb2xkYCBpbnRlcmFjdGlvbnMNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspOndhcm1fY29sZChjb2xkfHdhcm0pIiwgIlxcMShcXDIpIiwgUGFyYW1ldGVyKSwNCiAgICAjIEFkanVzdCBmb3IgYXNzYXlfdGVtcF9kaWZmDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKVxcKChjb2xkfHdhcm0pXFwpOmFzc2F5X3RlbXBfZGlmZiIsICJcXDEoXFwyKTogYXNzYXlfdGVtcF9kaWZmIiwgUGFyYW1ldGVyKSwNCiAgICAjIFJlbW92ZSAic2NhbGUiIGZyb20gcG9wX3NpemUNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJzY2FsZXBvcF9zaXplIiwgInBvcF9zaXplIiwgUGFyYW1ldGVyKQ0KICApICU+JQ0KICAjIFJvdW5kIG51bWJlcnMgdG8gMyBkZWNpbWFsIHBvaW50cw0KICBtdXRhdGUoYWNyb3NzKGMoRXN0aW1hdGUsIFEyLjUsIFE5Ny41KSwgfiByb3VuZCguLCAzKSkpICU+JQ0KICBzZWxlY3QoUGFyYW1ldGVyLCBFc3RpbWF0ZSwgYExvd2VyIENJYCA9IFEyLjUsIGBVcHBlciBDSWAgPSBROTcuNSkgJT4lDQogIGthYmxlKCkgJT4lDQogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBwb3NpdGlvbiA9ICJjZW50ZXIiLCBmaXhlZF90aGVhZCA9IFRSVUUpICU+JQ0KICBjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSwgYm9yZGVyX3JpZ2h0ID0gVFJVRSkgJT4lDQogIHJvd19zcGVjKDAsIGJhY2tncm91bmQgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIsIGJvbGQgPSBUUlVFKSAlPiUNCiAga2FibGVfc3R5bGluZyhmaXhlZF90aGVhZCA9IFRSVUUpDQpgYGANCg0KIyMjIyAqRGF0YSB2aXN1YWxpc2F0aW9uKg0KYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0PTEwfQ0KDQojIEdlbmVyYXRlIHByZWRpY3Rpb25zDQplbW1lYW5zX3BvcF9zaXplIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5WUl9tb2RlbF9wb3Bfc2l6ZSwNCiAgc3BlY3MgPSB+IHBvcF9zaXplIHwgdHJhaXRfdHlwZSAqIHdhcm1fY29sZCwNCiAgYXQgPSBsaXN0KHBvcF9zaXplID0gc2VxKG1pbihkYXRhJHBvcF9zaXplLCBuYS5ybT1UKSwgbWF4KGRhdGEkcG9wX3NpemUsIG5hLnJtPVQpLCBieSA9IDUwKSwNCiAgICAgICAgICAgIGFzc2F5X3RlbXBfZGlmZiA9IDApKQ0KICApICMgQ29uZGl0aW9uYWwgZWZmZWN0cyBvbiBhc3NheV90ZW1wX2RpZmYgPSAwDQoNCiMgQ2FsY3VsYXRlIHJhbmdlIG9mIHZhbHVlcyBmb3IgZWFjaCBjYXRlZ29yeQ0KcmFuZ2VfZGYgPC0gZGF0YSAlPiUNCiAgZ3JvdXBfYnkodHJhaXRfdHlwZSwgd2FybV9jb2xkKSAlPiUNCiAgc3VtbWFyaXplKA0KICAgIG1pbl9wb3Bfc2l6ZSA9IG1pbihwb3Bfc2l6ZSwgbmEucm09VCksDQogICAgbWF4X3BvcF9zaXplID0gbWF4KHBvcF9zaXplLCBuYS5ybT1UKQ0KICApDQoNCmVtbWVhbnNfcG9wX3NpemUkdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19wb3Bfc2l6ZSR0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYm9keV9zaXplIiwgImZlY3VuZGl0eSIsICJzdXJ2aXZhbCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQm9keSBzaXplIiwgIkZlY3VuZGl0eSIsICJTdXJ2aXZhbCIpKQ0KDQplbW1lYW5zX3BvcF9zaXplJHdhcm1fY29sZCA8LSBmYWN0b3IoZW1tZWFuc19wb3Bfc2l6ZSR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KDQojIFRhaWxvciBwcmVkaWN0aW9ucyB0byB0aGUgcmFuZ2Ugb2YgdGhlIGRhdGENCmVtbWVhbnNfcG9wX3NpemUgPC0gZW1tZWFuc19wb3Bfc2l6ZSAlPiUNCiAgbGVmdF9qb2luKHJhbmdlX2RmLCBieSA9IGMoInRyYWl0X3R5cGUiLCAid2FybV9jb2xkIikpICU+JQ0KICBmaWx0ZXIoDQogICAgcG9wX3NpemUgPj0gbWluX3BvcF9zaXplLA0KICAgIHBvcF9zaXplIDw9IG1heF9wb3Bfc2l6ZQ0KICApDQoNCiMgQ2FsY3VsYXRlIHNhbXBsZSBzaXplcyBhbmQgc3R1ZHkgY291bnRzIGZvciBwb3B1bGF0aW9uIHNpemUNCnNhbXBsZV9zaXplc19wb3Bfc2l6ZSA8LSBkYXRhICU+JQ0KICBmaWx0ZXIoaXMubmEocG9wX3NpemUpPT1GQUxTRSkgJT4lIA0KICBncm91cF9ieSh0cmFpdF90eXBlLCB3YXJtX2NvbGQpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgZXN0aW1hdGVzID0gbigpLA0KICAgIHN0dWRpZXMgPSBuX2Rpc3RpbmN0KHJlZikNCiAgKQ0KDQojIFBsb3QNCmdncGxvdCgpICsgDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgIyBIb3Jpem9udGFsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSkgKyANCiAgICBnZW9tX3BvaW50KGRhdGEgPSBkYXRhLCAgIyBFZmZlY3Qgc2l6ZXMsIHNjYWxlZCBieSBwcmVjaXNpb24NCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gcG9wX3NpemUsIA0KICAgICAgICAgICAgICAgICAgICAgIHkgPSBsblZSLCANCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMS9zcXJ0KHZhcl9sblZSKSwgDQogICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwgDQogICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNywgDQogICAgICAgICAgICAgICAgICBzdHJva2UgPSAxLA0KICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjA1KSkgKyANCiAgICAgZ2VvbV9yaWJib24oZGF0YSA9IGVtbWVhbnNfcG9wX3NpemUsICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IHBvcF9zaXplLA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICBhbHBoYSA9IC41KSArIA0KICAgICBnZW9tX2xpbmUoZGF0YSA9IGVtbWVhbnNfcG9wX3NpemUsICMgUHJlZGljdGVkIHJlZ3Jlc3Npb24gbGluZQ0KICAgICAgICAgICAgICAgYWVzKHkgPSBlbW1lYW4sDQogICAgICAgICAgICAgICAgICAgeCA9IHBvcF9zaXplLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArICANCiAgICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXNfcG9wX3NpemUsIA0KICAgICAgICAgICAgICBhZXMoeCA9IEluZiwgDQogICAgICAgICAgICAgICAgICB5ID0gaWZlbHNlKHdhcm1fY29sZCA9PSAiV2FybSIsIC0yLCAtMi43NSksICAjIFNhbXBsZSBzaXplcw0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEuMDUsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGZhY2V0X3dyYXAofiB0cmFpdF90eXBlLCBuY29sID0gMSkgKyAgIyBEaWZmZXJlbnQgcGFuZWxzIGZvciBlYWNoIHRyYWl0DQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgbGFicyh4ID0gIlBvcHVsYXRpb24gc2l6ZSIsIHkgPSAibG5WUiIsIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCA4KSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNSwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIyKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICB5bGltKC0zLjUsIDMuNSkNCg0KZ2dzYXZlKGZpbGUgPSAiZmlnL2xuVlJfcG9wX3NpemUucG5nIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNywgZHBpID0gNTAwKQ0KYGBgDQoNCiMjIyAqKkFsbCBtb2RlcmF0b3JzKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5WUiB+IDAgKyB0cmFpdF90eXBlOndhcm1fY29sZCArIA0KICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOmFzc2F5X3RlbXBfZGlmZiArIA0KICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOnNjYWxlKHNlbGVjdF90ZW1wX2RpZmYpICsNCiAgICAgICAgICAgICAgICB0cmFpdF90eXBlOndhcm1fY29sZDpzY2FsZShnZW5fc2VsZWN0aW9uKSArIA0KICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOnNjYWxlKGdlbl9jb21tb25fZ2FyZGVuKSArICMgU2VwYXJhdGUgZWZmZWN0cyBieSB0cmFpdCB0eXBlDQogICAgICAgICAgICAgICAgKHRyYWl0X3R5cGUtMXxyZWYpICsgIyBDb3JyZWxhdGlvbiBiZXR3ZWVuIHRyYWl0cyBhbW9uZyBzdHVkaWVzDQogICAgICAgICAgICAgICAgKDF8c3BlY2llcykgKyAjIFNwZWNpZXMtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfGdyKHBoeWxvZ2VueSwgY292ID0gcGh5bG9fbWF0cml4KSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5WUikpICMgVmFyaWFuY2UgY292YXJpYW5jZSBtYXRpeCBvZiBjb3JyZWxhdGVkIHNhbXBsaW5nIHZhcmlhbmNlcw0KDQojIERlZmluZSBwcmlvcnMNCnByaW9yID0gYygNCiAgcHJpb3IoY29uc3RhbnQoMSksIGNsYXNzID0gInNpZ21hIikNCikgIyBCZWNhdXNlIHRoZSByZXNpZHVhbCB2YXJpYW5jZS1jb3ZhcmlhbmNlIHN0cnVjdHVyZSBpcyBzcGVjaWZpZWQgaW4gZmNvciwgdGhlcmUgaXMgbm8gbmVlZCB0byBlc3RpbWF0ZSBzaWdtYSBzbyBpdCBpcyBsZWZ0IGFzIGEgY29uc3RhbnQNCg0KIyBGaXQgbW9kZWwNCmxuVlJfbW9kZWxfYWxsX21vZGVyYXRvcnMgPC0gYnJtKGZvcm11bGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IGdhdXNzaWFuKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEyID0gbGlzdChwaHlsb19tYXRyaXggPSBwaHlsb19tYXRyaXgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZDVl9sblZSID0gVkNWX2xuVlIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yID0gcHJpb3IsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXIgPSA0MDAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXJtdXAgPSAyMDAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYWlucyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEyMykgDQoNCiMgU2F2ZSBtb2RlbA0Kc2F2ZVJEUyhsblZSX21vZGVsX2FsbF9tb2RlcmF0b3JzLCBmaWxlID0gIlJEYXRhL2xuVlJfbW9kZWxfYWxsX21vZGVyYXRvcnMucmRzIikNCmBgYA0KDQojIyMjICpNb2RlbCBvdXRwdXQqDQpgYGB7cn0NCiMgTG9hZCBtb2RlbA0KbG5WUl9tb2RlbF9hbGxfbW9kZXJhdG9ycyA8LSByZWFkUkRTKCJSRGF0YS9sblZSX21vZGVsX2FsbF9tb2RlcmF0b3JzLnJkcyIpDQoNCiMgRGlzcGxheSBtb2RlbCBvdXRwdXQgDQpzdW1tYXJ5KGxuVlJfbW9kZWxfYWxsX21vZGVyYXRvcnMpDQoNCiMgQ2xlYW5lZCBtb2RlbCBvdXRwdXQNCmFzLmRhdGEuZnJhbWUoZml4ZWYobG5WUl9tb2RlbF9hbGxfbW9kZXJhdG9ycywgc3VtbWFyeSA9IFRSVUUpKSAlPiUNCiAgIyBSZW5hbWUgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGZvciBjbGVhbmVyIGRpc3BsYXkNCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJQYXJhbWV0ZXIiKSAlPiUNCiAgbXV0YXRlKA0KICAgICMgU2ltcGxpZnkgYHRyYWl0X3R5cGVgIGFuZCBgd2FybV9jb2xkYCBpbnRlcmFjdGlvbnMNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspOndhcm1fY29sZChjb2xkfHdhcm0pIiwgIlxcMShcXDIpIiwgUGFyYW1ldGVyKSwNCiAgICAjIEFkanVzdCBmb3IgYXNzYXlfdGVtcF9kaWZmDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKVxcKChjb2xkfHdhcm0pXFwpOmFzc2F5X3RlbXBfZGlmZiIsICJcXDEoXFwyKTogYXNzYXlfdGVtcF9kaWZmIiwgUGFyYW1ldGVyKSwNCiAgICAjIFJlbW92ZSAic2NhbGUiIGZyb20gYWxsIG1vZGVyYXRvciB2YXJpYWJsZXMNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJzY2FsZSIsICIiLCBQYXJhbWV0ZXIpDQogICkgJT4lDQogICMgUm91bmQgbnVtYmVycyB0byAzIGRlY2ltYWwgcG9pbnRzDQogIG11dGF0ZShhY3Jvc3MoYyhFc3RpbWF0ZSwgUTIuNSwgUTk3LjUpLCB+IHJvdW5kKC4sIDMpKSkgJT4lDQogIHNlbGVjdChQYXJhbWV0ZXIsIEVzdGltYXRlLCBgTG93ZXIgQ0lgID0gUTIuNSwgYFVwcGVyIENJYCA9IFE5Ny41KSAlPiUNCiAga2FibGUoKSAlPiUNCiAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImNlbnRlciIsIGZpeGVkX3RoZWFkID0gVFJVRSkgJT4lDQogIGNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFLCBib3JkZXJfcmlnaHQgPSBUUlVFKSAlPiUNCiAgcm93X3NwZWMoMCwgYmFja2dyb3VuZCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIiwgYm9sZCA9IFRSVUUpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZpeGVkX3RoZWFkID0gVFJVRSkNCg0KDQojIEdlbmVyYXRlIHByZWRpY3RlZCB2YWx1ZXMgYXQgZGlmZmVyZW50IGFzc2F5IHRlbXBlcmF0dXJlcw0KZW1tZWFuc19mdWxsX21vZGVsIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5WUl9tb2RlbF9hbGxfbW9kZXJhdG9ycywNCiAgc3BlY3MgPSB+IGFzc2F5X3RlbXBfZGlmZiAqIHNlbGVjdF90ZW1wX2RpZmYgKiBnZW5fc2VsZWN0aW9uICogZ2VuX2NvbW1vbl9nYXJkZW4gfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3QoYXNzYXlfdGVtcF9kaWZmID0gYygtOC41LCAtNCwgMCwgNCwgNSwgLTUsIDE3LCAyMCkpICMgUHJlZGljdCBhdCB1bmlxdWUgbWluLCBjb250cm9sLCBtYXggdmFsdWVzDQopKQ0KDQojIENhbGN1bGF0ZSByYW5nZSBvZiB2YWx1ZXMgZm9yIGVhY2ggY2F0ZWdvcnkNCnJhbmdlX2RmIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtaW5fYXNzYXkgPSBtaW4oYXNzYXlfdGVtcF9kaWZmKSwNCiAgICBtYXhfYXNzYXkgPSBtYXgoYXNzYXlfdGVtcF9kaWZmKSwNCiAgICBjb250cm9sX2Fzc2F5ID0gMA0KICApDQoNCmVtbWVhbnNfZnVsbF9tb2RlbCR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX2Z1bGxfbW9kZWwkdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KZW1tZWFuc19mdWxsX21vZGVsJHdhcm1fY29sZCA8LSBmYWN0b3IoZW1tZWFuc19mdWxsX21vZGVsJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgVGFpbG9yIHByZWRpY3Rpb25zIHRvIHRoZSByYW5nZSBvZiB0aGUgZGF0YQ0KZW1tZWFuc19mdWxsX21vZGVsICU+JQ0KICBsZWZ0X2pvaW4ocmFuZ2VfZGYsIGJ5ID0gYygidHJhaXRfdHlwZSIsICJ3YXJtX2NvbGQiKSkgJT4lDQogIGZpbHRlcigNCiAgICBhc3NheV90ZW1wX2RpZmYgPT0gbWluX2Fzc2F5IHwNCiAgICBhc3NheV90ZW1wX2RpZmYgPT0gbWF4X2Fzc2F5IHwNCiAgICBhc3NheV90ZW1wX2RpZmYgPT0gY29udHJvbF9hc3NheSkgJT4lIA0KICAgIGRwbHlyOjpzZWxlY3QoLW1pbl9hc3NheSwgLW1heF9hc3NheSwgLWNvbnRyb2xfYXNzYXkpICU+JSANCiAgICBtdXRhdGUocGVyY2VudGFnZV9jaGFuZ2UgPSAoZXhwKGVtbWVhbikgLSAxKSAqIDEwMCwNCiAgICAgICAgICAgcGVyY2VudGFnZV9sb3dlcl9IUEQgPSAoZXhwKGxvd2VyLkhQRCkgLSAxKSAqIDEwMCwNCiAgICAgICAgICAgcGVyY2VudGFnZV91cHBlcl9IUEQgPSAoZXhwKHVwcGVyLkhQRCkgLSAxKSAqIDEwMCkgJT4lDQogIG11dGF0ZShhY3Jvc3MoYyhlbW1lYW4sIA0KICAgICAgICAgICAgICAgICAgbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgIHVwcGVyLkhQRCwgDQogICAgICAgICAgICAgICAgICBwZXJjZW50YWdlX2NoYW5nZSwNCiAgICAgICAgICAgICAgICAgIHBlcmNlbnRhZ2VfbG93ZXJfSFBELCANCiAgICAgICAgICAgICAgICAgIHBlcmNlbnRhZ2VfdXBwZXJfSFBEKSwgfiByb3VuZCguLCAzKSkpICU+JSAgICMgUm91bmQgbnVtYmVycyB0byAzIGRlY2ltYWwgcG9pbnRzDQogIGthYmxlKCkgJT4lDQogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBwb3NpdGlvbiA9ICJjZW50ZXIiLCBmaXhlZF90aGVhZCA9IFRSVUUpICU+JQ0KICBjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSwgYm9yZGVyX3JpZ2h0ID0gVFJVRSkgJT4lDQogIHJvd19zcGVjKDAsIGJhY2tncm91bmQgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIsIGJvbGQgPSBUUlVFKSAlPiUNCiAga2FibGVfc3R5bGluZyhmaXhlZF90aGVhZCA9IFRSVUUpDQoNCmBgYA0KDQojIyMjICpEYXRhIHZpc3VhbGlzYXRpb24qDQoNCioqTWFyZ2luYWwgbWVhbnMqKiANCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD0xMH0NCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMgYXQgYXNzYXlfdGVtcF9kaWZmID0gMCwgb3IgNSBkZWdyZWVzIGJlbG93IG9yIGFib3ZlIHRoZSBjb250cm9sIHRlbXBlcmF0dXJlcw0KZW1tZWFuc19mdWxsX21vZGVsIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5WUl9tb2RlbF9hbGxfbW9kZXJhdG9ycywNCiAgc3BlY3MgPSB+IGFzc2F5X3RlbXBfZGlmZiAqIHNlbGVjdF90ZW1wX2RpZmYgKiBnZW5fc2VsZWN0aW9uICogZ2VuX2NvbW1vbl9nYXJkZW4gfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3QoYXNzYXlfdGVtcF9kaWZmID0gYygtNSwgMCwgNSkgIyBSZS1hY2NsaW1hdGVkIHRvIGNvbnRyb2wsIG9yIDUgZGVncmVlcyBhYm92ZS9iZWxvdyB0aGUgY29udG9sDQogICkpKSAjIDIgZ2VuZXJhdGlvbnMgb2YgY29tbW9uIGdhcmRlbg0KDQojIFJlbmFtZSB2YXJpYWJsZSBsZXZlbHMNCmVtbWVhbnNfZnVsbF9tb2RlbCR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX2Z1bGxfbW9kZWwkdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KZW1tZWFuc19mdWxsX21vZGVsJHdhcm1fY29sZCA8LSBmYWN0b3IoZW1tZWFuc19mdWxsX21vZGVsJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQplbW1lYW5zX2Z1bGxfbW9kZWwNCg0KIyBQbG90DQpnZ3Bsb3QoKSArDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgIyBIb3Jpem9udGFsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSwgDQogICAgICAgICAgICAgICBsd2Q9MSkgKw0KICAgIGdlb21fcXVhc2lyYW5kb20oZGF0YSA9IGRhdGEsICAgICAjIFBsb3QgZWZmZWN0IHNpemVzLCBzY2FsZWQgYnkgcHJlY2lzaW9uDQogICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5WUiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMS9zcXJ0KHZhcl9sblZSKSksIA0KICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLA0KICAgICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4zLCANCiAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gMC4zKSArDQogICAgZ2VvbV9lcnJvcmJhcihkYXRhID0gZmlsdGVyKGVtbWVhbnNfZnVsbF9tb2RlbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID09ICItNSIpLCAgIyA1IGRlZ3JlZXMgYmVsb3cgY29udHJvbCAoYmFja2dyb3VuZCkNCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTp3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQpLCANCiAgICAgICAgICAgICAgICAgIGNvbG9yPSJ3aGl0ZSIsDQogICAgICAgICAgICAgICAgICBzaXplID0gMi43NSwNCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4xNiwNCiAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fbnVkZ2UoeD0tMC4yNSkpICsNCiAgICBnZW9tX3BvaW50KGRhdGEgPSBmaWx0ZXIoZW1tZWFuc19mdWxsX21vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPT0gIi01IiksICAjIDUgZGVncmVlcyBiZWxvdyBjb250cm9sIChiYWNrZ3JvdW5kKQ0KICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgeSA9IGVtbWVhbiksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDQuNSwgDQogICAgICAgICAgICAgICBzdHJva2UgPSAyLA0KICAgICAgICAgICAgICAgY29sb3I9IndoaXRlIiwNCiAgICAgICAgICAgICAgIGZpbGwgPSAid2hpdGUiLA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4PS0wLjI1KSkgKw0KICAgIGdlb21fZXJyb3JiYXIoZGF0YSA9IGZpbHRlcihlbW1lYW5zX2Z1bGxfbW9kZWwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2F5X3RlbXBfZGlmZiA9PSAiLTUiKSwgIyA1IGRlZ3JlZXMgYmVsb3cgY29udHJvbCAoY3JlZGlibGUgaW50ZXJ2YWxzKQ0KICAgICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCksIA0KICAgICAgICAgICAgICAgICAgY29sb3I9IiMwNkI0QkEiLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIsDQogICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMTIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9LTAuMjUpKSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gZmlsdGVyKGVtbWVhbnNfZnVsbF9tb2RlbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID09ICItNSIpLCAjIDUgZGVncmVlcyBiZWxvdyBjb250cm9sICAocG9pbnQgZXN0aW1hdGVzKQ0KICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgeSA9IGVtbWVhbiksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDMuNSwgDQogICAgICAgICAgICAgICBzdHJva2UgPSAyLA0KICAgICAgICAgICAgICAgY29sb3I9IiMwNkI0QkEiLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9LTAuMjUpKSArDQoNCiAgICAgIGdlb21fZXJyb3JiYXIoZGF0YSA9IGZpbHRlcihlbW1lYW5zX2Z1bGxfbW9kZWwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2F5X3RlbXBfZGlmZiA9PSAiMCIpLCAgIyBjb250cm9sIHRlbXBlcmF0dXJlIChiYWNrZ3JvdW5kKQ0KICAgICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCksIA0KICAgICAgICAgICAgICAgICAgY29sb3I9IndoaXRlIiwNCiAgICAgICAgICAgICAgICAgIHNpemUgPSAyLjc1LA0KICAgICAgICAgICAgICAgICAgd2lkdGggPSAwLjE2LA0KICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4PTApKSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gZmlsdGVyKGVtbWVhbnNfZnVsbF9tb2RlbCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID09ICIwIiksICAjIGNvbnRyb2wgdGVtcGVyYXR1cmUgKGJhY2tncm91bmQpDQogICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICB5ID0gZW1tZWFuKSwNCiAgICAgICAgICAgICAgIHNoYXBlID0gMjIsDQogICAgICAgICAgICAgICBzaXplID0gNC41LCANCiAgICAgICAgICAgICAgIHN0cm9rZSA9IDIsDQogICAgICAgICAgICAgICBjb2xvcj0id2hpdGUiLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9MCkpICsNCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBmaWx0ZXIoZW1tZWFuc19mdWxsX21vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPT0gIjAiKSwgIyBjb250cm9sIHRlbXBlcmF0dXJlIChjcmVkaWJsZSBpbnRlcnZhbHMpDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBEKSwgDQogICAgICAgICAgICAgICAgICBjb2xvcj0iYmxhY2siLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIsDQogICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMTIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9MCkpICsNCiAgICBnZW9tX3BvaW50KGRhdGEgPSBmaWx0ZXIoZW1tZWFuc19mdWxsX21vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPT0gIjAiKSwgIyBjb250cm9sIHRlbXBlcmF0dXJlIChwb2ludCBlc3RpbWF0ZXMpDQogICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICB5ID0gZW1tZWFuKSwNCiAgICAgICAgICAgICAgIHNoYXBlID0gMjIsDQogICAgICAgICAgICAgICBzaXplID0gMy41LCANCiAgICAgICAgICAgICAgIHN0cm9rZSA9IDIsDQogICAgICAgICAgICAgICBjb2xvcj0iYmxhY2siLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9MCkpICsNCiAgDQogICAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBmaWx0ZXIoZW1tZWFuc19mdWxsX21vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPT0gIjUiKSwgICMgNSBkZWdyZWVzIGFib3ZlIGNvbnRyb2wgKGJhY2tncm91bmQpDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBEKSwgDQogICAgICAgICAgICAgICAgICBjb2xvcj0id2hpdGUiLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIuNzUsDQogICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMTYsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9MC4yNSkpICsNCiAgICBnZW9tX3BvaW50KGRhdGEgPSBmaWx0ZXIoZW1tZWFuc19mdWxsX21vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPT0gIjUiKSwgICMgNSBkZWdyZWVzIGFib3ZlIGNvbnRyb2wgKGJhY2tncm91bmQpDQogICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICB5ID0gZW1tZWFuKSwNCiAgICAgICAgICAgICAgIHNoYXBlID0gMjMsDQogICAgICAgICAgICAgICBzaXplID0gNC41LCANCiAgICAgICAgICAgICAgIHN0cm9rZSA9IDIsDQogICAgICAgICAgICAgICBjb2xvcj0id2hpdGUiLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9MC4yNSkpICsNCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBmaWx0ZXIoZW1tZWFuc19mdWxsX21vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPT0gIjUiKSwgIyA1IGRlZ3JlZXMgYWJvdmUgY29udHJvbCAoY3JlZGlibGUgaW50ZXJ2YWxzKQ0KICAgICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCksIA0KICAgICAgICAgICAgICAgICAgY29sb3I9IiNFODA3NTYiLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIsDQogICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMTIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9MC4yNSkpICsNCiAgICBnZW9tX3BvaW50KGRhdGEgPSBmaWx0ZXIoZW1tZWFuc19mdWxsX21vZGVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPT0gIjUiKSwgIyA1IGRlZ3JlZXMgYWJvdmUgY29udHJvbCAocG9pbnQgZXN0aW1hdGVzKQ0KICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOndhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgeSA9IGVtbWVhbiksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIzLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDMuNSwgDQogICAgICAgICAgICAgICBzdHJva2UgPSAyLA0KICAgICAgICAgICAgICAgY29sb3I9IiNFODA3NTYiLA0KICAgICAgICAgICAgICAgZmlsbCA9ICJ3aGl0ZSIsDQogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHg9MC4yNSkpICsNCiAgDQogICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXMsICAjIFNhbXBsZSBzaXplIGFubm90YXRpb25zIA0KICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6d2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgIHkgPSAzLA0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIA0KICAgIHRoZW1lX2J3KCkgKyAgICAgIyBDdXN0b21pemUgdGhlIHBsb3QNCiAgICBsYWJzKHkgPSAibG5WUiIsIHggPSAiIikgKw0KICAgIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgOCkpKyANCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiLCAiIzA2QjRCQSIsICIjRTgwNzU2IiwgIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiQ29sZCIgPSAiIzA2QjRCQSIsICJXYXJtIiA9ICIjRTgwNzU2IikpICsgICMgVGV4dCBjb2xvdXINCiAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTQpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuNSkpICsNCiAgICBndWlkZXMoZmlsbCA9ICJub25lIiwgc2l6ZSA9ICJub25lIikrDQogICAgY29vcmRfZmxpcCgpICsgDQogICAgeWxpbSgtMy41LCAzLjUpDQoNCmdnc2F2ZShmaWxlID0gImZpZy9sblZSX2FsbF9tb2RlcmF0b3JzX21hcmdpbmFsX21lYW5zLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDgsIGRwaSA9IDUwMCkNCmBgYA0KDQoqKk92ZXJhbGwgdHJlbmQgd2l0aCBhc3NheSB0ZW1wZXJhdHVyZSoqIA0KYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0PTEwfQ0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucyBmb3IgYWxsIGFzc2F5IHRlbXBlcmF0dXJlcw0KZW1tZWFuc19mdWxsX21vZGVsX2Fzc2F5IDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5WUl9tb2RlbF9hbGxfbW9kZXJhdG9ycywNCiAgc3BlY3MgPSB+IGFzc2F5X3RlbXBfZGlmZiAqIHNlbGVjdF90ZW1wX2RpZmYgKiBnZW5fc2VsZWN0aW9uICogZ2VuX2NvbW1vbl9nYXJkZW4gfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3QoYXNzYXlfdGVtcF9kaWZmID0gc2VxKG1pbihkYXRhJGFzc2F5X3RlbXBfZGlmZiksIG1heChkYXRhJGFzc2F5X3RlbXBfZGlmZiksIGJ5ID0gMC41KSAjIFJlLWFjY2xpbWF0ZWQgdG8gY29udHJvbCwgb3IgNSBkZWdyZWVzIGFib3ZlL2JlbG93IHRoZSBjb250b2wNCiAgKSkpIA0KDQoNCiMgQ2FsY3VsYXRlIHJhbmdlIG9mIHZhbHVlcyBmb3IgZWFjaCBjYXRlZ29yeQ0KcmFuZ2VfZGYgPC0gZGF0YSAlPiUNCiAgZ3JvdXBfYnkodHJhaXRfdHlwZSwgd2FybV9jb2xkKSAlPiUNCiAgc3VtbWFyaXplKA0KICAgIG1pbl9hc3NheV90ZW1wX2RpZmYgPSBtaW4oYXNzYXlfdGVtcF9kaWZmKSwNCiAgICBtYXhfYXNzYXlfdGVtcF9kaWZmID0gbWF4KGFzc2F5X3RlbXBfZGlmZikNCiAgKQ0KDQojIFJlbmFtZSB2YXJpYWJsZSBsZXZlbHMNCmVtbWVhbnNfZnVsbF9tb2RlbF9hc3NheSR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX2Z1bGxfbW9kZWxfYXNzYXkkdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KZW1tZWFuc19mdWxsX21vZGVsX2Fzc2F5JHdhcm1fY29sZCA8LSBmYWN0b3IoZW1tZWFuc19mdWxsX21vZGVsX2Fzc2F5JHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgVGFpbG9yIHByZWRpY3Rpb25zIHRvIHRoZSByYW5nZSBvZiB0aGUgZGF0YQ0KZW1tZWFuc19mdWxsX21vZGVsX2Fzc2F5IDwtIGVtbWVhbnNfZnVsbF9tb2RlbF9hc3NheSAlPiUNCiAgbGVmdF9qb2luKHJhbmdlX2RmLCBieSA9IGMoInRyYWl0X3R5cGUiLCAid2FybV9jb2xkIikpICU+JQ0KICBmaWx0ZXIoDQogICAgYXNzYXlfdGVtcF9kaWZmID49IG1pbl9hc3NheV90ZW1wX2RpZmYsDQogICAgYXNzYXlfdGVtcF9kaWZmIDw9IG1heF9hc3NheV90ZW1wX2RpZmYNCiAgKQ0KDQoNCiMgUGxvdA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArICANCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCAjIFZlcnRpY2FsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSkgKyANCiAgICBnZW9tX3BvaW50KGRhdGEgPSBkYXRhLCAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBhc3NheV90ZW1wX2RpZmYsIA0KICAgICAgICAgICAgICAgICAgICAgIHkgPSBsblZSLCANCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMS9zcXJ0KHZhcl9sblZSKSwgDQogICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwgDQogICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNywgDQogICAgICAgICAgICAgICAgICBzdHJva2UgPSAxLA0KICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjA1KSkgKyANCiAgICAgZ2VvbV9yaWJib24oZGF0YSA9IGVtbWVhbnNfZnVsbF9tb2RlbF9hc3NheSwgIyBTaGFkZWQgYXJlYSBmb3IgY3JlZGlibGUgaW50ZXJ2YWxzDQogICAgICAgICAgICAgICAgIGFlcyh4ID0gYXNzYXlfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICBhbHBoYSA9IC41KSArIA0KICAgICBnZW9tX2xpbmUoZGF0YSA9IGVtbWVhbnNfZnVsbF9tb2RlbF9hc3NheSwgICMgUHJlZGljdGVkIHJlZ3Jlc3Npb24gbGluZQ0KICAgICAgICAgICAgICAgYWVzKHkgPSBlbW1lYW4sDQogICAgICAgICAgICAgICAgICAgeCA9IGFzc2F5X3RlbXBfZGlmZiwNCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKyANCiAgDQogICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXMsIA0KICAgICAgICAgICAgICBhZXMoeCA9IEluZiwgDQogICAgICAgICAgICAgICAgICB5ID0gaWZlbHNlKHdhcm1fY29sZCA9PSAiV2FybSIsIC0yLCAtMi43NSksICAjIFNhbXBsZSBzaXplcw0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEuMDUsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIA0KICBmYWNldF93cmFwKH4gdHJhaXRfdHlwZSwgbmNvbCA9IDEpICsgIyBEaWZmZXJlbnQgcGFuZWxzIGZvciBlYWNoIHRyYWl0DQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgbGFicyh4ID0gIkFzc2F5IHRlbXBlcmF0dXJlIGRpZmZlcmVuY2UiLCB5ID0gImxuVlIiLA0KICAgICAgIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCA4KSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNSwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIyKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTMuNSwgMy41KSkNCg0KZ2dzYXZlKGZpbGUgPSAiZmlnL2xuVlJfYWxsX21vZGVyYXRvcnNfYXNzYXlfdGVtcF9kaWZmLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDEwLCBkcGkgPSA1MDApDQpgYGANCg0KDQoNCiMgKipQdWJsaWNhdGlvbiBiaWFzKiogDQoNCiMjICoqQ2hhbmdlcyBpbiBtZWFuIHJlc3BvbnNlcyAobG5SUikqKiB7LnRhYnNldCAudGFic2V0X2ZhZGUgLnRhYnNldF9waWxsc30NCg0KIyMjICoqRWdnZXIncyByZWdyZXNzaW9uKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5SUiB+IDAgKyB0cmFpdF90eXBlOndhcm1fY29sZCArIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOmFzc2F5X3RlbXBfZGlmZiArIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOnZhcl9sblJSICsgIyBTZXBhcmF0ZSBlZmZlY3RzIGJ5IHRyYWl0IHR5cGUNCiAgICAgICAgICAgICAgICAodHJhaXRfdHlwZS0xfHJlZikgKyAjIENvcnJlbGF0aW9uIGJldHdlZW4gdHJhaXRzIGFtb25nIHN0dWRpZXMNCiAgICAgICAgICAgICAgICAoMXxzcGVjaWVzKSArICMgU3BlY2llcy1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8Z3IocGh5bG9nZW55LCBjb3YgPSBwaHlsb19tYXRyaXgpKSArICMgUGh5bG9nZW5ldGljIHJlbGF0ZWRuZXNzDQogICAgICAgICAgICAgICAgKDF8ZXhwZXJpbWVudF9JRCkgKyAjIEV4cGVyaW1lbnQtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfG9icykgKyAjIE9ic2VydmF0aW9uLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICBmY29yKFZDVl9sblJSKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5SUl9tb2RlbF9wdWJfYmlhc192YXIgPC0gYnJtKGZvcm11bGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBnYXVzc2lhbigpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEyID0gbGlzdChwaHlsb19tYXRyaXggPSBwaHlsb19tYXRyaXgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWQ1ZfbG5SUiA9IFZDVl9sblJSKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IgPSBwcmlvciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyID0gNDAwMCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm11cCA9IDIwMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYWlucyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JlcyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gMTIzKSANCiMgU2F2ZSBtb2RlbA0Kc2F2ZVJEUyhsblJSX21vZGVsX3B1Yl9iaWFzX3ZhciwgZmlsZSA9ICJSRGF0YS9sblJSX21vZGVsX3B1Yl9iaWFzX3Zhci5yZHMiKQ0KYGBgDQoNCiMjIyMgKk1vZGVsIG91dHB1dCoNCmBgYHtyfQ0KIyBMb2FkIG1vZGVsDQpsblJSX21vZGVsX3B1Yl9iaWFzX3ZhciA8LSByZWFkUkRTKCJSRGF0YS9sblJSX21vZGVsX3B1Yl9iaWFzX3Zhci5yZHMiKQ0KDQojIERpc3BsYXkgbW9kZWwgb3V0cHV0IA0Kc3VtbWFyeShsblJSX21vZGVsX3B1Yl9iaWFzX3ZhcikNCg0KIyBDbGVhbmVkIG1vZGVsIG91dHB1dA0KYXMuZGF0YS5mcmFtZShmaXhlZihsblJSX21vZGVsX3B1Yl9iaWFzX3Zhciwgc3VtbWFyeSA9IFRSVUUpKSAlPiUNCiAgIyBSZW5hbWUgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGZvciBjbGVhbmVyIGRpc3BsYXkNCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJQYXJhbWV0ZXIiKSAlPiUgDQogIG11dGF0ZSgNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspOndhcm1fY29sZChjb2xkfHdhcm0pIiwgIlxcMShcXDIpIiwgUGFyYW1ldGVyKSwNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspXFwod2FybVxcKTphc3NheV90ZW1wX2RpZmYiLCAiXFwxKHdhcm0pOiBhc3NheV90ZW1wX2RpZmYiLCBQYXJhbWV0ZXIpDQogICkgJT4lDQogICMgUm91bmQgbnVtYmVycyB0byAzIGRlY2ltYWwgcG9pbnRzDQogIG11dGF0ZShhY3Jvc3MoYyhFc3RpbWF0ZSwgUTIuNSwgUTk3LjUpLCB+IHJvdW5kKC4sIDMpKSkgJT4lDQogIHNlbGVjdChQYXJhbWV0ZXIsIEVzdGltYXRlLCBgTG93ZXIgQ0lgID0gUTIuNSwgYFVwcGVyIENJYCA9IFE5Ny41KSAlPiUNCiAga2FibGUoKSAlPiUNCiAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImNlbnRlciIsIGZpeGVkX3RoZWFkID0gVFJVRSkgJT4lDQogIGNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFLCBib3JkZXJfcmlnaHQgPSBUUlVFKSAlPiUNCiAgcm93X3NwZWMoMCwgYmFja2dyb3VuZCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIiwgYm9sZCA9IFRSVUUpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZpeGVkX3RoZWFkID0gVFJVRSkNCmBgYA0KDQojIyMjICpEYXRhIHZpc3VhbGlzYXRpb24qDQoNCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD0xMH0NCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbWVhbnNfcHViX2JpYXNfdmFyIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5SUl9tb2RlbF9wdWJfYmlhc192YXIsDQogIHNwZWNzID0gfiB2YXJfbG5SUiB8IHRyYWl0X3R5cGUgKiB3YXJtX2NvbGQsDQogIGF0ID0gbGlzdCh2YXJfbG5SUiA9IHNlcSgwLCBtYXgoZGF0YSR2YXJfbG5SUiksIGJ5ID0gMC4xKSwNCiAgICAgICAgICAgIGFzc2F5X3RlbXBfZGlmZiA9IDApKQ0KICApICMgQ29uZGl0aW9uYWwgZWZmZWN0cyBvbiBhc3NheV90ZW1wX2RpZmYgPSAwDQoNCmVtbWVhbnNfcHViX2JpYXNfdmFyJHRyYWl0X3R5cGUgPC0gZmFjdG9yKGVtbWVhbnNfcHViX2JpYXNfdmFyJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfcHViX2JpYXNfdmFyJHdhcm1fY29sZCA8LSBmYWN0b3IoZW1tZWFuc19wdWJfYmlhc192YXIkd2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiY29sZCIsICJ3YXJtIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJDb2xkIiwgIldhcm0iKSkNCg0KIyBQbG90DQpnZ3Bsb3QoKSArIA0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUpICsgDQogICAgZ2VvbV9wb2ludChkYXRhID0gZGF0YSwgICMgRWZmZWN0IHNpemVzLCBzY2FsZWQgYnkgcHJlY2lzaW9uDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHZhcl9sblJSLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5SUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5SUiksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wMDEpKSArIA0KICAgICBnZW9tX3JpYmJvbihkYXRhID0gZW1tZWFuc19wdWJfYmlhc192YXIsICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IHZhcl9sblJSLA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICBhbHBoYSA9IC41KSArIA0KICAgICBnZW9tX2xpbmUoZGF0YSA9IGVtbWVhbnNfcHViX2JpYXNfdmFyLCAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSB2YXJfbG5SUiwNCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKyAgDQogICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzLCANCiAgICAgICAgICAgICAgYWVzKHggPSBJbmYsIA0KICAgICAgICAgICAgICAgICAgeSA9IGlmZWxzZSh3YXJtX2NvbGQgPT0gIldhcm0iLCAtMC44LCAtMS4zKSwgICMgU2FtcGxlIHNpemVzDQogICAgICAgICAgICAgICAgICBsYWJlbCA9IHBhc3RlMCgiayA9ICIsIGVzdGltYXRlcywgIiAoIiwgc3R1ZGllcywgIikiKSwNCiAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgIGhqdXN0ID0gMS4wNSwgc2l6ZSA9IDUsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgZmFjZXRfd3JhcCh+IHRyYWl0X3R5cGUsIG5jb2wgPSAxKSArICAjIERpZmZlcmVudCBwYW5lbHMgZm9yIGVhY2ggdHJhaXQNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICBsYWJzKHggPSAiU2FtcGxpbmcgdmFyaWFuY2Ugb2YgbG5SUiIsIHkgPSAibG5SUiIsIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCA4KSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNSwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIyKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTEuNSwgMS41KSwgeGxpbSA9IGMoMCwgMC4zKSkNCg0KZ2dzYXZlKGZpbGUgPSAiZmlnL2xuUlJfcHViX2JpYXNfdmFyLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIGRwaSA9IDUwMCkNCmBgYA0KDQojIyMgKipQdWJsaWNhdGlvbiB5ZWFyKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5SUiB+IDAgKyB0cmFpdF90eXBlOndhcm1fY29sZCArIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOmFzc2F5X3RlbXBfZGlmZiArIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOnNjYWxlKHB1Yl95ZWFyKSArICMgU2VwYXJhdGUgZWZmZWN0cyBieSB0cmFpdCB0eXBlDQogICAgICAgICAgICAgICAgKHRyYWl0X3R5cGUtMXxyZWYpICsgIyBDb3JyZWxhdGlvbiBiZXR3ZWVuIHRyYWl0cyBhbW9uZyBzdHVkaWVzDQogICAgICAgICAgICAgICAgKDF8c3BlY2llcykgKyAjIFNwZWNpZXMtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfGdyKHBoeWxvZ2VueSwgY292ID0gcGh5bG9fbWF0cml4KSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5SUikpICMgVmFyaWFuY2UgY292YXJpYW5jZSBtYXRpeCBvZiBjb3JyZWxhdGVkIHNhbXBsaW5nIHZhcmlhbmNlcw0KDQojIERlZmluZSBwcmlvcnMNCnByaW9yID0gYygNCiAgcHJpb3IoY29uc3RhbnQoMSksIGNsYXNzID0gInNpZ21hIikNCikgIyBCZWNhdXNlIHRoZSByZXNpZHVhbCB2YXJpYW5jZS1jb3ZhcmlhbmNlIHN0cnVjdHVyZSBpcyBzcGVjaWZpZWQgaW4gZmNvciwgdGhlcmUgaXMgbm8gbmVlZCB0byBlc3RpbWF0ZSBzaWdtYSBzbyBpdCBpcyBsZWZ0IGFzIGEgY29uc3RhbnQNCg0KIyBGaXQgbW9kZWwNCmxuUlJfbW9kZWxfcHViX2JpYXNfeWVhciA8LSBicm0oZm9ybXVsYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IGdhdXNzaWFuKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTIgPSBsaXN0KHBoeWxvX21hdHJpeCA9IHBoeWxvX21hdHJpeCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZDVl9sblJSID0gVkNWX2xuUlIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmlvciA9IHByaW9yLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXIgPSA0MDAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FybXVwID0gMjAwMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhaW5zID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZWQgPSAxMjMpIA0KIyBTYXZlIG1vZGVsDQpzYXZlUkRTKGxuUlJfbW9kZWxfcHViX2JpYXNfeWVhciwgZmlsZSA9ICJSRGF0YS9sblJSX21vZGVsX3B1Yl9iaWFzX3llYXIucmRzIikNCmBgYA0KDQojIyMjICpNb2RlbCBvdXRwdXQqDQpgYGB7cn0NCiMgTG9hZCBtb2RlbA0KbG5SUl9tb2RlbF9wdWJfYmlhc195ZWFyIDwtIHJlYWRSRFMoIlJEYXRhL2xuUlJfbW9kZWxfcHViX2JpYXNfeWVhci5yZHMiKQ0KDQojIERpc3BsYXkgbW9kZWwgb3V0cHV0IA0Kc3VtbWFyeShsblJSX21vZGVsX3B1Yl9iaWFzX3llYXIpDQoNCiMgQ2xlYW5lZCBtb2RlbCBvdXRwdXQNCmFzLmRhdGEuZnJhbWUoZml4ZWYobG5SUl9tb2RlbF9wdWJfYmlhc195ZWFyLCBzdW1tYXJ5ID0gVFJVRSkpICU+JQ0KICAjIFJlbmFtZSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgZm9yIGNsZWFuZXIgZGlzcGxheQ0KICByb3duYW1lc190b19jb2x1bW4odmFyID0gIlBhcmFtZXRlciIpICU+JQ0KICBtdXRhdGUoDQogICAgIyBTaW1wbGlmeSBgdHJhaXRfdHlwZWAgYW5kIGB3YXJtX2NvbGRgIGludGVyYWN0aW9ucw0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKyk6d2FybV9jb2xkKGNvbGR8d2FybSkiLCAiXFwxKFxcMikiLCBQYXJhbWV0ZXIpLA0KICAgICMgQWRqdXN0IGZvciBhc3NheV90ZW1wX2RpZmYNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspXFwoKGNvbGR8d2FybSlcXCk6YXNzYXlfdGVtcF9kaWZmIiwgIlxcMShcXDIpOiBhc3NheV90ZW1wX2RpZmYiLCBQYXJhbWV0ZXIpLA0KICAgICMgUmVtb3ZlICJzY2FsZSIgZnJvbSBwdWJfeWVhcg0KICAgIFBhcmFtZXRlciA9IGdzdWIoInNjYWxlcHViX3llYXIiLCAicHViX3llYXIiLCBQYXJhbWV0ZXIpDQogICkgJT4lDQogICMgUm91bmQgbnVtYmVycyB0byAzIGRlY2ltYWwgcG9pbnRzDQogIG11dGF0ZShhY3Jvc3MoYyhFc3RpbWF0ZSwgUTIuNSwgUTk3LjUpLCB+IHJvdW5kKC4sIDMpKSkgJT4lDQogIHNlbGVjdChQYXJhbWV0ZXIsIEVzdGltYXRlLCBgTG93ZXIgQ0lgID0gUTIuNSwgYFVwcGVyIENJYCA9IFE5Ny41KSAlPiUNCiAga2FibGUoKSAlPiUNCiAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImNlbnRlciIsIGZpeGVkX3RoZWFkID0gVFJVRSkgJT4lDQogIGNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFLCBib3JkZXJfcmlnaHQgPSBUUlVFKSAlPiUNCiAgcm93X3NwZWMoMCwgYmFja2dyb3VuZCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIiwgYm9sZCA9IFRSVUUpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZpeGVkX3RoZWFkID0gVFJVRSkNCmBgYA0KDQojIyMjICpEYXRhIHZpc3VhbGlzYXRpb24qDQoNCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD0xMH0NCg0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucw0KZW1tZWFuc19wdWJfYmlhc195ZWFyIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5SUl9tb2RlbF9wdWJfYmlhc195ZWFyLA0KICBzcGVjcyA9IH4gcHViX3llYXIgfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3QocHViX3llYXIgPSBzZXEobWluKGRhdGEkcHViX3llYXIpLCBtYXgoZGF0YSRwdWJfeWVhciksIGJ5ID0gMSksDQogICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPSAwKSkNCiAgKSAjIENvbmRpdGlvbmFsIGVmZmVjdHMgb24gYXNzYXlfdGVtcF9kaWZmID0gMA0KDQojIENhbGN1bGF0ZSByYW5nZSBvZiB2YWx1ZXMgZm9yIGVhY2ggY2F0ZWdvcnkNCnJhbmdlX2RmIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtaW5fcHViX3llYXIgPSBtaW4ocHViX3llYXIpLA0KICAgIG1heF9wdWJfeWVhciA9IG1heChwdWJfeWVhcikNCiAgKQ0KDQplbW1lYW5zX3B1Yl9iaWFzX3llYXIkdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19wdWJfYmlhc195ZWFyJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfcHViX2JpYXNfeWVhciR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfcHViX2JpYXNfeWVhciR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KDQojIFRhaWxvciBwcmVkaWN0aW9ucyB0byB0aGUgcmFuZ2Ugb2YgdGhlIGRhdGENCmVtbWVhbnNfcHViX2JpYXNfeWVhciA8LSBlbW1lYW5zX3B1Yl9iaWFzX3llYXIgJT4lDQogIGxlZnRfam9pbihyYW5nZV9kZiwgYnkgPSBjKCJ0cmFpdF90eXBlIiwgIndhcm1fY29sZCIpKSAlPiUNCiAgZmlsdGVyKA0KICAgIHB1Yl95ZWFyID49IG1pbl9wdWJfeWVhciwNCiAgICBwdWJfeWVhciA8PSBtYXhfcHViX3llYXINCiAgKQ0KDQojIFBsb3QNCmdncGxvdCgpICsgDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgIyBIb3Jpem9udGFsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSkgKyANCiAgICBnZW9tX3BvaW50KGRhdGEgPSBkYXRhLCAgIyBFZmZlY3Qgc2l6ZXMsIHNjYWxlZCBieSBwcmVjaXNpb24NCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gcHViX3llYXIsIA0KICAgICAgICAgICAgICAgICAgICAgIHkgPSBsblJSLCANCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMS9zcXJ0KHB1Yl95ZWFyKSwgDQogICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwgDQogICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNywgDQogICAgICAgICAgICAgICAgICBzdHJva2UgPSAxLA0KICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjA1KSkgKyANCiAgICAgZ2VvbV9yaWJib24oZGF0YSA9IGVtbWVhbnNfcHViX2JpYXNfeWVhciwgIyBTaGFkZWQgYXJlYSBmb3IgY3JlZGlibGUgaW50ZXJ2YWxzDQogICAgICAgICAgICAgICAgIGFlcyh4ID0gcHViX3llYXIsDQogICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgIGFscGhhID0gLjUpICsgDQogICAgIGdlb21fbGluZShkYXRhID0gZW1tZWFuc19wdWJfYmlhc195ZWFyLCAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSBwdWJfeWVhciwNCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKyAgDQogICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzLCANCiAgICAgICAgICAgICAgYWVzKHggPSBJbmYsIA0KICAgICAgICAgICAgICAgICAgeSA9IGlmZWxzZSh3YXJtX2NvbGQgPT0gIldhcm0iLCAtMC45LCAtMS4zKSwgICMgU2FtcGxlIHNpemVzDQogICAgICAgICAgICAgICAgICBsYWJlbCA9IHBhc3RlMCgiayA9ICIsIGVzdGltYXRlcywgIiAoIiwgc3R1ZGllcywgIikiKSwNCiAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgIGhqdXN0ID0gMS4wNSwgc2l6ZSA9IDUsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgZmFjZXRfd3JhcCh+IHRyYWl0X3R5cGUsIG5jb2wgPSAxKSArICAjIERpZmZlcmVudCBwYW5lbHMgZm9yIGVhY2ggdHJhaXQNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICBsYWJzKHggPSAiU2FtcGxpbmcgdmFyaWFuY2Ugb2YgbG5SUiIsIHkgPSAibG5SUiIsIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCA4KSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNSwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIyKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSArIA0KICAgIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygtMS41LCAxLjUpKQ0KDQpnZ3NhdmUoZmlsZSA9ICJmaWcvbG5SUl9wdWJfYmlhc195ZWFyLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIGRwaSA9IDUwMCkNCmBgYA0KDQojIyAqKkNoYW5nZXMgaW4gcmVsYXRpdmUgdHJhaXQgdmFyaWFuY2UgKGxuQ1ZSKSoqIHsudGFic2V0IC50YWJzZXRfZmFkZSAudGFic2V0X3BpbGxzfQ0KDQojIyMgKipFZ2dlcidzIHJlZ3Jlc3Npb24qKiANCg0KIyMjIyAqTW9kZWwgc3BlY2lmaWNhdGlvbioNCmBgYHtyLCBldmFsID0gRn0NCiMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KZm9ybXVsYSA8LSBiZihsbkNWUiB+IDAgKyB0cmFpdF90eXBlOndhcm1fY29sZCArIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOmFzc2F5X3RlbXBfZGlmZiArIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOnZhcl9sbkNWUiArICMgU2VwYXJhdGUgZWZmZWN0cyBieSB0cmFpdCB0eXBlDQogICAgICAgICAgICAgICAgKHRyYWl0X3R5cGUtMXxyZWYpICsgIyBDb3JyZWxhdGlvbiBiZXR3ZWVuIHRyYWl0cyBhbW9uZyBzdHVkaWVzDQogICAgICAgICAgICAgICAgKDF8c3BlY2llcykgKyAjIFNwZWNpZXMtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfGdyKHBoeWxvZ2VueSwgY292ID0gcGh5bG9fbWF0cml4KSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5DVlIpKSAjIFZhcmlhbmNlIGNvdmFyaWFuY2UgbWF0aXggb2YgY29ycmVsYXRlZCBzYW1wbGluZyB2YXJpYW5jZXMNCg0KIyBEZWZpbmUgcHJpb3JzDQpwcmlvciA9IGMoDQogIHByaW9yKGNvbnN0YW50KDEpLCBjbGFzcyA9ICJzaWdtYSIpDQopICMgQmVjYXVzZSB0aGUgcmVzaWR1YWwgdmFyaWFuY2UtY292YXJpYW5jZSBzdHJ1Y3R1cmUgaXMgc3BlY2lmaWVkIGluIGZjb3IsIHRoZXJlIGlzIG5vIG5lZWQgdG8gZXN0aW1hdGUgc2lnbWEgc28gaXQgaXMgbGVmdCBhcyBhIGNvbnN0YW50DQoNCiMgRml0IG1vZGVsDQpsbkNWUl9tb2RlbF9wdWJfYmlhc192YXIgPC0gYnJtKGZvcm11bGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBnYXVzc2lhbigpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEyID0gbGlzdChwaHlsb19tYXRyaXggPSBwaHlsb19tYXRyaXgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWQ1ZfbG5DVlIgPSBWQ1ZfbG5DVlIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmlvciA9IHByaW9yLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXIgPSA0MDAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FybXVwID0gMjAwMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhaW5zID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZWQgPSAxMjMpIA0KIyBTYXZlIG1vZGVsDQpzYXZlUkRTKGxuQ1ZSX21vZGVsX3B1Yl9iaWFzX3ZhciwgZmlsZSA9ICJSRGF0YS9sbkNWUl9tb2RlbF9wdWJfYmlhc192YXIucmRzIikNCmBgYA0KDQojIyMjICpNb2RlbCBvdXRwdXQqDQpgYGB7cn0NCiMgTG9hZCBtb2RlbA0KbG5DVlJfbW9kZWxfcHViX2JpYXNfdmFyIDwtIHJlYWRSRFMoIlJEYXRhL2xuQ1ZSX21vZGVsX3B1Yl9iaWFzX3Zhci5yZHMiKQ0KDQojIERpc3BsYXkgbW9kZWwgb3V0cHV0IA0Kc3VtbWFyeShsbkNWUl9tb2RlbF9wdWJfYmlhc192YXIpDQoNCiMgQ2xlYW5lZCBtb2RlbCBvdXRwdXQNCmFzLmRhdGEuZnJhbWUoZml4ZWYobG5DVlJfbW9kZWxfcHViX2JpYXNfdmFyLCBzdW1tYXJ5ID0gVFJVRSkpICU+JQ0KICAjIFJlbmFtZSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgZm9yIGNsZWFuZXIgZGlzcGxheQ0KICByb3duYW1lc190b19jb2x1bW4odmFyID0gIlBhcmFtZXRlciIpICU+JSANCiAgbXV0YXRlKA0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKyk6d2FybV9jb2xkKGNvbGR8d2FybSkiLCAiXFwxKFxcMikiLCBQYXJhbWV0ZXIpLA0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKylcXCh3YXJtXFwpOmFzc2F5X3RlbXBfZGlmZiIsICJcXDEod2FybSk6IGFzc2F5X3RlbXBfZGlmZiIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkRhdGEgdmlzdWFsaXNhdGlvbioNCg0KYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0PTEwfQ0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucw0KZW1tZWFuc19wdWJfYmlhc192YXIgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsbkNWUl9tb2RlbF9wdWJfYmlhc192YXIsDQogIHNwZWNzID0gfiB2YXJfbG5DVlIgfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3QodmFyX2xuQ1ZSID0gc2VxKDAsIG1heChkYXRhJHZhcl9sbkNWUiksIGJ5ID0gMSksDQogICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPSAwKSkNCiAgKSAjIENvbmRpdGlvbmFsIGVmZmVjdHMgb24gYXNzYXlfdGVtcF9kaWZmID0gMA0KDQplbW1lYW5zX3B1Yl9iaWFzX3ZhciR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX3B1Yl9iaWFzX3ZhciR0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYm9keV9zaXplIiwgImZlY3VuZGl0eSIsICJzdXJ2aXZhbCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQm9keSBzaXplIiwgIkZlY3VuZGl0eSIsICJTdXJ2aXZhbCIpKQ0KDQplbW1lYW5zX3B1Yl9iaWFzX3ZhciR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfcHViX2JpYXNfdmFyJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgUGxvdA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsICAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSB2YXJfbG5DVlIsIA0KICAgICAgICAgICAgICAgICAgICAgIHkgPSBsbkNWUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5DVlIpLCANCiAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgICBzaGFwZSA9IDIxLCANCiAgICAgICAgICAgICAgICAgIGFscGhhID0gMC43LCANCiAgICAgICAgICAgICAgICAgIHN0cm9rZSA9IDEsDQogICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IDAuMSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX3B1Yl9iaWFzX3ZhciwgIyBTaGFkZWQgYXJlYSBmb3IgY3JlZGlibGUgaW50ZXJ2YWxzDQogICAgICAgICAgICAgICAgIGFlcyh4ID0gdmFyX2xuQ1ZSLA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICBhbHBoYSA9IC41KSArIA0KICAgICBnZW9tX2xpbmUoZGF0YSA9IGVtbWVhbnNfcHViX2JpYXNfdmFyLCAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSB2YXJfbG5DVlIsDQogICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsgIA0KICAgICBnZW9tX3RleHQoZGF0YSA9IHNhbXBsZV9zaXplcywgDQogICAgICAgICAgICAgIGFlcyh4ID0gSW5mLCANCiAgICAgICAgICAgICAgICAgIHkgPSBpZmVsc2Uod2FybV9jb2xkID09ICJXYXJtIiwgLTEuOSwgLTIuODUpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBmYWNldF93cmFwKH4gdHJhaXRfdHlwZSwgbmNvbCA9IDEpICsgICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJTYW1wbGluZyB2YXJpYW5jZSBvZiBsbkNWUiIsIHkgPSAibG5DVlIiLCBjb2wgPSAiUmVnaW1lIikgKw0KICB0aGVtZV9idygpICsgDQogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgOCkpKyANCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjUsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxOCksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAyMikpICsNCiAgICBndWlkZXMoZmlsbCA9ICJub25lIiwgc2l6ZSA9ICJub25lIikgKw0KICAgIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygtMy41LCAzLjUpLCB4bGltID0gYygwLCA2KSkNCg0KDQpnZ3NhdmUoZmlsZSA9ICJmaWcvbG5DVlJfcHViX2JpYXNfdmFyLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIGRwaSA9IDUwMCkNCmBgYA0KDQojIyMgKipQdWJsaWNhdGlvbiB5ZWFyKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5DVlIgfiAwICsgdHJhaXRfdHlwZTp3YXJtX2NvbGQgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICB0cmFpdF90eXBlOndhcm1fY29sZDphc3NheV90ZW1wX2RpZmYgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICB0cmFpdF90eXBlOndhcm1fY29sZDpzY2FsZShwdWJfeWVhcikgKyAjIFNlcGFyYXRlIGVmZmVjdHMgYnkgdHJhaXQgdHlwZQ0KICAgICAgICAgICAgICAgICh0cmFpdF90eXBlLTF8cmVmKSArICMgQ29ycmVsYXRpb24gYmV0d2VlbiB0cmFpdHMgYW1vbmcgc3R1ZGllcw0KICAgICAgICAgICAgICAgICgxfHNwZWNpZXMpICsgIyBTcGVjaWVzLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxncihwaHlsb2dlbnksIGNvdiA9IHBoeWxvX21hdHJpeCkpICsgIyBQaHlsb2dlbmV0aWMgcmVsYXRlZG5lc3MNCiAgICAgICAgICAgICAgICAoMXxleHBlcmltZW50X0lEKSArICMgRXhwZXJpbWVudC1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8b2JzKSArICMgT2JzZXJ2YXRpb24tbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgIGZjb3IoVkNWX2xuQ1ZSKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5DVlJfbW9kZWxfcHViX2JpYXNfeWVhciA8LSBicm0oZm9ybXVsYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IGdhdXNzaWFuKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTIgPSBsaXN0KHBoeWxvX21hdHJpeCA9IHBoeWxvX21hdHJpeCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZDVl9sbkNWUiA9IFZDVl9sbkNWUiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yID0gcHJpb3IsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OSwgbWF4X3RyZWVkZXB0aCA9IDE1KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDQwMDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXJtdXAgPSAyMDAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFpbnMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEyMykgDQojIFNhdmUgbW9kZWwNCnNhdmVSRFMobG5DVlJfbW9kZWxfcHViX2JpYXNfeWVhciwgZmlsZSA9ICJSRGF0YS9sbkNWUl9tb2RlbF9wdWJfYmlhc195ZWFyLnJkcyIpDQpgYGANCg0KIyMjIyAqTW9kZWwgb3V0cHV0Kg0KYGBge3J9DQojIExvYWQgbW9kZWwNCmxuQ1ZSX21vZGVsX3B1Yl9iaWFzX3llYXIgPC0gcmVhZFJEUygiUkRhdGEvbG5DVlJfbW9kZWxfcHViX2JpYXNfeWVhci5yZHMiKQ0KDQojIERpc3BsYXkgbW9kZWwgb3V0cHV0IA0Kc3VtbWFyeShsbkNWUl9tb2RlbF9wdWJfYmlhc195ZWFyKQ0KDQojIENsZWFuZWQgbW9kZWwgb3V0cHV0DQphcy5kYXRhLmZyYW1lKGZpeGVmKGxuQ1ZSX21vZGVsX3B1Yl9iaWFzX3llYXIsIHN1bW1hcnkgPSBUUlVFKSkgJT4lDQogICMgUmVuYW1lIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBmb3IgY2xlYW5lciBkaXNwbGF5DQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAiUGFyYW1ldGVyIikgJT4lDQogIG11dGF0ZSgNCiAgICAjIFNpbXBsaWZ5IGB0cmFpdF90eXBlYCBhbmQgYHdhcm1fY29sZGAgaW50ZXJhY3Rpb25zDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKTp3YXJtX2NvbGQoY29sZHx3YXJtKSIsICJcXDEoXFwyKSIsIFBhcmFtZXRlciksDQogICAgIyBBZGp1c3QgZm9yIGFzc2F5X3RlbXBfZGlmZg0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKylcXCgoY29sZHx3YXJtKVxcKTphc3NheV90ZW1wX2RpZmYiLCAiXFwxKFxcMik6IGFzc2F5X3RlbXBfZGlmZiIsIFBhcmFtZXRlciksDQogICAgIyBSZW1vdmUgInNjYWxlIiBmcm9tIHB1Yl95ZWFyDQogICAgUGFyYW1ldGVyID0gZ3N1Yigic2NhbGVwdWJfeWVhciIsICJwdWJfeWVhciIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkRhdGEgdmlzdWFsaXNhdGlvbioNCg0KYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0PTEwfQ0KDQojIEdlbmVyYXRlIHByZWRpY3Rpb25zDQplbW1lYW5zX3B1Yl9iaWFzX3llYXIgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsbkNWUl9tb2RlbF9wdWJfYmlhc195ZWFyLA0KICBzcGVjcyA9IH4gcHViX3llYXIgfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3QocHViX3llYXIgPSBzZXEobWluKGRhdGEkcHViX3llYXIpLCBtYXgoZGF0YSRwdWJfeWVhciksIGJ5ID0gMSksDQogICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPSAwKSkNCiAgKSAjIENvbmRpdGlvbmFsIGVmZmVjdHMgb24gYXNzYXlfdGVtcF9kaWZmID0gMA0KDQojIENhbGN1bGF0ZSByYW5nZSBvZiB2YWx1ZXMgZm9yIGVhY2ggY2F0ZWdvcnkNCnJhbmdlX2RmIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtaW5fcHViX3llYXIgPSBtaW4ocHViX3llYXIpLA0KICAgIG1heF9wdWJfeWVhciA9IG1heChwdWJfeWVhcikNCiAgKQ0KDQplbW1lYW5zX3B1Yl9iaWFzX3llYXIkdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19wdWJfYmlhc195ZWFyJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfcHViX2JpYXNfeWVhciR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfcHViX2JpYXNfeWVhciR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KDQojIFRhaWxvciBwcmVkaWN0aW9ucyB0byB0aGUgcmFuZ2Ugb2YgdGhlIGRhdGENCmVtbWVhbnNfcHViX2JpYXNfeWVhciA8LSBlbW1lYW5zX3B1Yl9iaWFzX3llYXIgJT4lDQogIGxlZnRfam9pbihyYW5nZV9kZiwgYnkgPSBjKCJ0cmFpdF90eXBlIiwgIndhcm1fY29sZCIpKSAlPiUNCiAgZmlsdGVyKA0KICAgIHB1Yl95ZWFyID49IG1pbl9wdWJfeWVhciwNCiAgICBwdWJfeWVhciA8PSBtYXhfcHViX3llYXINCiAgKQ0KDQojIFBsb3QNCmdncGxvdCgpICsgDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgIyBIb3Jpem9udGFsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSkgKyANCiAgICBnZW9tX3BvaW50KGRhdGEgPSBkYXRhLCAgIyBFZmZlY3Qgc2l6ZXMsIHNjYWxlZCBieSBwcmVjaXNpb24NCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gcHViX3llYXIsIA0KICAgICAgICAgICAgICAgICAgICAgIHkgPSBsbkNWUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydChwdWJfeWVhciksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX3B1Yl9iaWFzX3llYXIsICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IHB1Yl95ZWFyLA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICBhbHBoYSA9IC41KSArIA0KICAgICBnZW9tX2xpbmUoZGF0YSA9IGVtbWVhbnNfcHViX2JpYXNfeWVhciwgIyBQcmVkaWN0ZWQgcmVncmVzc2lvbiBsaW5lDQogICAgICAgICAgICAgICBhZXMoeSA9IGVtbWVhbiwNCiAgICAgICAgICAgICAgICAgICB4ID0gcHViX3llYXIsDQogICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsgIA0KICAgICBnZW9tX3RleHQoZGF0YSA9IHNhbXBsZV9zaXplcywgDQogICAgICAgICAgICAgIGFlcyh4ID0gSW5mLCANCiAgICAgICAgICAgICAgICAgIHkgPSBpZmVsc2Uod2FybV9jb2xkID09ICJXYXJtIiwgLTEuOSwgLTIuODUpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBmYWNldF93cmFwKH4gdHJhaXRfdHlwZSwgbmNvbCA9IDEpICsgICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJQdWJsaWNhdGlvbiB5ZWFyIiwgeSA9ICJsbkNWUiIsIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCA4KSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNSwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIyKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSArIA0KICAgIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygtMywgMykpDQoNCmdnc2F2ZShmaWxlID0gImZpZy9sbkNWUl9wdWJfYmlhc195ZWFyLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIGRwaSA9IDUwMCkNCmBgYA0KDQoNCiMjICoqQ2hhbmdlcyBpbiB0cmFpdCB2YXJpYW5jZSAobG5WUikqKiB7LnRhYnNldCAudGFic2V0X2ZhZGUgLnRhYnNldF9waWxsc30NCg0KIyMjICoqRWdnZXIncyByZWdyZXNzaW9uKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5WUiB+IDAgKyB0cmFpdF90eXBlOndhcm1fY29sZCArIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOmFzc2F5X3RlbXBfZGlmZiArIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWl0X3R5cGU6d2FybV9jb2xkOnZhcl9sblZSICsgIyBTZXBhcmF0ZSBlZmZlY3RzIGJ5IHRyYWl0IHR5cGUNCiAgICAgICAgICAgICAgICAodHJhaXRfdHlwZS0xfHJlZikgKyAjIENvcnJlbGF0aW9uIGJldHdlZW4gdHJhaXRzIGFtb25nIHN0dWRpZXMNCiAgICAgICAgICAgICAgICAoMXxzcGVjaWVzKSArICMgU3BlY2llcy1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8Z3IocGh5bG9nZW55LCBjb3YgPSBwaHlsb19tYXRyaXgpKSArICMgUGh5bG9nZW5ldGljIHJlbGF0ZWRuZXNzDQogICAgICAgICAgICAgICAgKDF8ZXhwZXJpbWVudF9JRCkgKyAjIEV4cGVyaW1lbnQtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfG9icykgKyAjIE9ic2VydmF0aW9uLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICBmY29yKFZDVl9sblZSKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5WUl9tb2RlbF9wdWJfYmlhc192YXIgPC0gYnJtKGZvcm11bGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBnYXVzc2lhbigpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEyID0gbGlzdChwaHlsb19tYXRyaXggPSBwaHlsb19tYXRyaXgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWQ1ZfbG5WUiA9IFZDVl9sblZSKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IgPSBwcmlvciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyID0gNDAwMCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm11cCA9IDIwMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYWlucyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JlcyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gMTIzKSANCiMgU2F2ZSBtb2RlbA0Kc2F2ZVJEUyhsblZSX21vZGVsX3B1Yl9iaWFzX3ZhciwgZmlsZSA9ICJSRGF0YS9sblZSX21vZGVsX3B1Yl9iaWFzX3Zhci5yZHMiKQ0KYGBgDQoNCiMjIyMgKk1vZGVsIG91dHB1dCoNCmBgYHtyfQ0KIyBMb2FkIG1vZGVsDQpsblZSX21vZGVsX3B1Yl9iaWFzX3ZhciA8LSByZWFkUkRTKCJSRGF0YS9sblZSX21vZGVsX3B1Yl9iaWFzX3Zhci5yZHMiKQ0KDQojIERpc3BsYXkgbW9kZWwgb3V0cHV0IA0Kc3VtbWFyeShsblZSX21vZGVsX3B1Yl9iaWFzX3ZhcikNCg0KIyBDbGVhbmVkIG1vZGVsIG91dHB1dA0KYXMuZGF0YS5mcmFtZShmaXhlZihsblZSX21vZGVsX3B1Yl9iaWFzX3Zhciwgc3VtbWFyeSA9IFRSVUUpKSAlPiUNCiAgIyBSZW5hbWUgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGZvciBjbGVhbmVyIGRpc3BsYXkNCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJQYXJhbWV0ZXIiKSAlPiUgDQogIG11dGF0ZSgNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspOndhcm1fY29sZChjb2xkfHdhcm0pIiwgIlxcMShcXDIpIiwgUGFyYW1ldGVyKSwNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspXFwod2FybVxcKTphc3NheV90ZW1wX2RpZmYiLCAiXFwxKHdhcm0pOiBhc3NheV90ZW1wX2RpZmYiLCBQYXJhbWV0ZXIpDQogICkgJT4lDQogICMgUm91bmQgbnVtYmVycyB0byAzIGRlY2ltYWwgcG9pbnRzDQogIG11dGF0ZShhY3Jvc3MoYyhFc3RpbWF0ZSwgUTIuNSwgUTk3LjUpLCB+IHJvdW5kKC4sIDMpKSkgJT4lDQogIHNlbGVjdChQYXJhbWV0ZXIsIEVzdGltYXRlLCBgTG93ZXIgQ0lgID0gUTIuNSwgYFVwcGVyIENJYCA9IFE5Ny41KSAlPiUNCiAga2FibGUoKSAlPiUNCiAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImNlbnRlciIsIGZpeGVkX3RoZWFkID0gVFJVRSkgJT4lDQogIGNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFLCBib3JkZXJfcmlnaHQgPSBUUlVFKSAlPiUNCiAgcm93X3NwZWMoMCwgYmFja2dyb3VuZCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIiwgYm9sZCA9IFRSVUUpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZpeGVkX3RoZWFkID0gVFJVRSkNCmBgYA0KDQojIyMjICpEYXRhIHZpc3VhbGlzYXRpb24qDQoNCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD0xMH0NCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbWVhbnNfcHViX2JpYXNfdmFyIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5WUl9tb2RlbF9wdWJfYmlhc192YXIsDQogIHNwZWNzID0gfiB2YXJfbG5WUiB8IHRyYWl0X3R5cGUgKiB3YXJtX2NvbGQsDQogIGF0ID0gbGlzdCh2YXJfbG5WUiA9IHNlcSgwLCBtYXgoZGF0YSR2YXJfbG5WUiksIGJ5ID0gMSksDQogICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPSAwKSkNCiAgKSAjIENvbmRpdGlvbmFsIGVmZmVjdHMgb24gYXNzYXlfdGVtcF9kaWZmID0gMA0KDQplbW1lYW5zX3B1Yl9iaWFzX3ZhciR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX3B1Yl9iaWFzX3ZhciR0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYm9keV9zaXplIiwgImZlY3VuZGl0eSIsICJzdXJ2aXZhbCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQm9keSBzaXplIiwgIkZlY3VuZGl0eSIsICJTdXJ2aXZhbCIpKQ0KDQplbW1lYW5zX3B1Yl9iaWFzX3ZhciR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfcHViX2JpYXNfdmFyJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgUGxvdA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsICAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSB2YXJfbG5WUiwgDQogICAgICAgICAgICAgICAgICAgICAgeSA9IGxuVlIsIA0KICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxL3NxcnQodmFyX2xuVlIpLCANCiAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgICBzaGFwZSA9IDIxLCANCiAgICAgICAgICAgICAgICAgIGFscGhhID0gMC43LCANCiAgICAgICAgICAgICAgICAgIHN0cm9rZSA9IDEsDQogICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IDAuMDUpKSArIA0KICAgICBnZW9tX3JpYmJvbihkYXRhID0gZW1tZWFuc19wdWJfYmlhc192YXIsICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IHZhcl9sblZSLA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICBhbHBoYSA9IC41KSArIA0KICAgICBnZW9tX2xpbmUoZGF0YSA9IGVtbWVhbnNfcHViX2JpYXNfdmFyLCAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSB2YXJfbG5WUiwNCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKyAgDQogICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzLCANCiAgICAgICAgICAgICAgYWVzKHggPSBJbmYsIA0KICAgICAgICAgICAgICAgICAgeSA9IGlmZWxzZSh3YXJtX2NvbGQgPT0gIldhcm0iLCAtMi4zLCAtMy4yNSksICAjIFNhbXBsZSBzaXplcw0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEuMDUsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGZhY2V0X3dyYXAofiB0cmFpdF90eXBlLCBuY29sID0gMSkgKyAgIyBEaWZmZXJlbnQgcGFuZWxzIGZvciBlYWNoIHRyYWl0DQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgbGFicyh4ID0gIlNhbXBsaW5nIHZhcmlhbmNlIG9mIGxuVlIiLCB5ID0gImxuVlIiLCBjb2wgPSAiUmVnaW1lIikgKw0KICB0aGVtZV9idygpICsgDQogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgOCkpKyANCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjUsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxOCksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAyMikpICsNCiAgICBndWlkZXMoZmlsbCA9ICJub25lIiwgc2l6ZSA9ICJub25lIikrDQogICAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0zLjUsIDMuNSksIHhsaW0gPSBjKDAsIDYpKQ0KDQoNCmdnc2F2ZShmaWxlID0gImZpZy9sblZSX3B1Yl9iaWFzX3Zhci5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA3LCBkcGkgPSA1MDApDQpgYGANCg0KIyMjICoqUHVibGljYXRpb24geWVhcioqIA0KDQojIyMjICpNb2RlbCBzcGVjaWZpY2F0aW9uKg0KYGBge3IsIGV2YWwgPSBGfQ0KIyBNb2RlbCBzcGVjaWZpY2F0aW9uDQpmb3JtdWxhIDwtIGJmKGxuVlIgfiAwICsgdHJhaXRfdHlwZTp3YXJtX2NvbGQgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICB0cmFpdF90eXBlOndhcm1fY29sZDphc3NheV90ZW1wX2RpZmYgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICB0cmFpdF90eXBlOndhcm1fY29sZDpzY2FsZShwdWJfeWVhcikgKyAjIFNlcGFyYXRlIGVmZmVjdHMgYnkgdHJhaXQgdHlwZQ0KICAgICAgICAgICAgICAgICh0cmFpdF90eXBlLTF8cmVmKSArICMgQ29ycmVsYXRpb24gYmV0d2VlbiB0cmFpdHMgYW1vbmcgc3R1ZGllcw0KICAgICAgICAgICAgICAgICgxfHNwZWNpZXMpICsgIyBTcGVjaWVzLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxncihwaHlsb2dlbnksIGNvdiA9IHBoeWxvX21hdHJpeCkpICsgIyBQaHlsb2dlbmV0aWMgcmVsYXRlZG5lc3MNCiAgICAgICAgICAgICAgICAoMXxleHBlcmltZW50X0lEKSArICMgRXhwZXJpbWVudC1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8b2JzKSArICMgT2JzZXJ2YXRpb24tbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgIGZjb3IoVkNWX2xuVlIpKSAjIFZhcmlhbmNlIGNvdmFyaWFuY2UgbWF0aXggb2YgY29ycmVsYXRlZCBzYW1wbGluZyB2YXJpYW5jZXMNCg0KIyBEZWZpbmUgcHJpb3JzDQpwcmlvciA9IGMoDQogIHByaW9yKGNvbnN0YW50KDEpLCBjbGFzcyA9ICJzaWdtYSIpDQopICMgQmVjYXVzZSB0aGUgcmVzaWR1YWwgdmFyaWFuY2UtY292YXJpYW5jZSBzdHJ1Y3R1cmUgaXMgc3BlY2lmaWVkIGluIGZjb3IsIHRoZXJlIGlzIG5vIG5lZWQgdG8gZXN0aW1hdGUgc2lnbWEgc28gaXQgaXMgbGVmdCBhcyBhIGNvbnN0YW50DQoNCiMgRml0IG1vZGVsDQpsblZSX21vZGVsX3B1Yl9iaWFzX3llYXIgPC0gYnJtKGZvcm11bGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBnYXVzc2lhbigpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEyID0gbGlzdChwaHlsb19tYXRyaXggPSBwaHlsb19tYXRyaXgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWQ1ZfbG5WUiA9IFZDVl9sblZSKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpb3IgPSBwcmlvciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyID0gNDAwMCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm11cCA9IDIwMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYWlucyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JlcyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gMTIzKSANCiMgU2F2ZSBtb2RlbA0Kc2F2ZVJEUyhsblZSX21vZGVsX3B1Yl9iaWFzX3llYXIsIGZpbGUgPSAiUkRhdGEvbG5WUl9tb2RlbF9wdWJfYmlhc195ZWFyLnJkcyIpDQpgYGANCg0KIyMjIyAqTW9kZWwgb3V0cHV0Kg0KYGBge3J9DQojIExvYWQgbW9kZWwNCmxuVlJfbW9kZWxfcHViX2JpYXNfeWVhciA8LSByZWFkUkRTKCJSRGF0YS9sblZSX21vZGVsX3B1Yl9iaWFzX3llYXIucmRzIikNCg0KIyBEaXNwbGF5IG1vZGVsIG91dHB1dCANCnN1bW1hcnkobG5WUl9tb2RlbF9wdWJfYmlhc195ZWFyKQ0KDQojIENsZWFuZWQgbW9kZWwgb3V0cHV0DQphcy5kYXRhLmZyYW1lKGZpeGVmKGxuVlJfbW9kZWxfcHViX2JpYXNfeWVhciwgc3VtbWFyeSA9IFRSVUUpKSAlPiUNCiAgIyBSZW5hbWUgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGZvciBjbGVhbmVyIGRpc3BsYXkNCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJQYXJhbWV0ZXIiKSAlPiUNCiAgbXV0YXRlKA0KICAgICMgU2ltcGxpZnkgYHRyYWl0X3R5cGVgIGFuZCBgd2FybV9jb2xkYCBpbnRlcmFjdGlvbnMNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspOndhcm1fY29sZChjb2xkfHdhcm0pIiwgIlxcMShcXDIpIiwgUGFyYW1ldGVyKSwNCiAgICAjIEFkanVzdCBmb3IgYXNzYXlfdGVtcF9kaWZmDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKVxcKChjb2xkfHdhcm0pXFwpOmFzc2F5X3RlbXBfZGlmZiIsICJcXDEoXFwyKTogYXNzYXlfdGVtcF9kaWZmIiwgUGFyYW1ldGVyKSwNCiAgICAjIFJlbW92ZSAic2NhbGUiIGZyb20gcHViX3llYXINCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJzY2FsZXB1Yl95ZWFyIiwgInB1Yl95ZWFyIiwgUGFyYW1ldGVyKQ0KICApICU+JQ0KICAjIFJvdW5kIG51bWJlcnMgdG8gMyBkZWNpbWFsIHBvaW50cw0KICBtdXRhdGUoYWNyb3NzKGMoRXN0aW1hdGUsIFEyLjUsIFE5Ny41KSwgfiByb3VuZCguLCAzKSkpICU+JQ0KICBzZWxlY3QoUGFyYW1ldGVyLCBFc3RpbWF0ZSwgYExvd2VyIENJYCA9IFEyLjUsIGBVcHBlciBDSWAgPSBROTcuNSkgJT4lDQogIGthYmxlKCkgJT4lDQogIGthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFLCBwb3NpdGlvbiA9ICJjZW50ZXIiLCBmaXhlZF90aGVhZCA9IFRSVUUpICU+JQ0KICBjb2x1bW5fc3BlYygxLCBib2xkID0gVFJVRSwgYm9yZGVyX3JpZ2h0ID0gVFJVRSkgJT4lDQogIHJvd19zcGVjKDAsIGJhY2tncm91bmQgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIsIGJvbGQgPSBUUlVFKSAlPiUNCiAga2FibGVfc3R5bGluZyhmaXhlZF90aGVhZCA9IFRSVUUpDQpgYGANCg0KIyMjIyAqRGF0YSB2aXN1YWxpc2F0aW9uKg0KDQpgYGB7ciwgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQ9MTB9DQojIEdlbmVyYXRlIHByZWRpY3Rpb25zDQplbW1lYW5zX3B1Yl9iaWFzX3llYXIgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsblZSX21vZGVsX3B1Yl9iaWFzX3llYXIsDQogIHNwZWNzID0gfiBwdWJfeWVhciB8IHRyYWl0X3R5cGUgKiB3YXJtX2NvbGQsDQogIGF0ID0gbGlzdChwdWJfeWVhciA9IHNlcShtaW4oZGF0YSRwdWJfeWVhciksIG1heChkYXRhJHB1Yl95ZWFyKSwgYnkgPSAxKSwNCiAgICAgICAgICAgIGFzc2F5X3RlbXBfZGlmZiA9IDApKQ0KICApICMgQ29uZGl0aW9uYWwgZWZmZWN0cyBvbiBhc3NheV90ZW1wX2RpZmYgPSAwDQoNCg0KIyBDYWxjdWxhdGUgcmFuZ2Ugb2YgdmFsdWVzIGZvciBlYWNoIGNhdGVnb3J5DQpyYW5nZV9kZiA8LSBkYXRhICU+JQ0KICBncm91cF9ieSh0cmFpdF90eXBlLCB3YXJtX2NvbGQpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWluX3B1Yl95ZWFyID0gbWluKHB1Yl95ZWFyKSwNCiAgICBtYXhfcHViX3llYXIgPSBtYXgocHViX3llYXIpDQogICkNCg0KZW1tZWFuc19wdWJfYmlhc195ZWFyJHRyYWl0X3R5cGUgPC0gZmFjdG9yKGVtbWVhbnNfcHViX2JpYXNfeWVhciR0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYm9keV9zaXplIiwgImZlY3VuZGl0eSIsICJzdXJ2aXZhbCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQm9keSBzaXplIiwgIkZlY3VuZGl0eSIsICJTdXJ2aXZhbCIpKQ0KDQplbW1lYW5zX3B1Yl9iaWFzX3llYXIkd2FybV9jb2xkIDwtIGZhY3RvcihlbW1lYW5zX3B1Yl9iaWFzX3llYXIkd2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiY29sZCIsICJ3YXJtIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJDb2xkIiwgIldhcm0iKSkNCg0KIyBUYWlsb3IgcHJlZGljdGlvbnMgdG8gdGhlIHJhbmdlIG9mIHRoZSBkYXRhDQplbW1lYW5zX3B1Yl9iaWFzX3llYXIgPC0gZW1tZWFuc19wdWJfYmlhc195ZWFyICU+JQ0KICBsZWZ0X2pvaW4ocmFuZ2VfZGYsIGJ5ID0gYygidHJhaXRfdHlwZSIsICJ3YXJtX2NvbGQiKSkgJT4lDQogIGZpbHRlcigNCiAgICBwdWJfeWVhciA+PSBtaW5fcHViX3llYXIsDQogICAgcHViX3llYXIgPD0gbWF4X3B1Yl95ZWFyDQogICkNCg0KIyBQbG90DQpnZ3Bsb3QoKSArIA0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUpICsgDQogICAgZ2VvbV9wb2ludChkYXRhID0gZGF0YSwgICMgRWZmZWN0IHNpemVzLCBzY2FsZWQgYnkgcHJlY2lzaW9uDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHB1Yl95ZWFyLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5WUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydChwdWJfeWVhciksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX3B1Yl9iaWFzX3llYXIsICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IHB1Yl95ZWFyLA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICBhbHBoYSA9IC41KSArIA0KICAgICBnZW9tX2xpbmUoZGF0YSA9IGVtbWVhbnNfcHViX2JpYXNfeWVhciwgIyBQcmVkaWN0ZWQgcmVncmVzc2lvbiBsaW5lDQogICAgICAgICAgICAgICBhZXMoeSA9IGVtbWVhbiwNCiAgICAgICAgICAgICAgICAgICB4ID0gcHViX3llYXIsDQogICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsgIA0KICAgICBnZW9tX3RleHQoZGF0YSA9IHNhbXBsZV9zaXplcywgDQogICAgICAgICAgICAgIGFlcyh4ID0gSW5mLCANCiAgICAgICAgICAgICAgICAgIHkgPSBpZmVsc2Uod2FybV9jb2xkID09ICJXYXJtIiwgLTIuMywgLTMuMjUpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBmYWNldF93cmFwKH4gdHJhaXRfdHlwZSwgbmNvbCA9IDEpICsgICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJTYW1wbGluZyB2YXJpYW5jZSBvZiBsblZSIiwgeSA9ICJsblZSIiwgY29sID0gIlJlZ2ltZSIpICsNCiAgdGhlbWVfYncoKSArIA0KICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDIsIDgpKSsgDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDI1LCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTgpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgICAgYXhpcy50ZXh0LnkgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwLCANCiAgICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCBoanVzdCA9IDAuNSksDQogICAgICAgICAgYXhpcy50ZXh0LnggPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuNSksDQogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMjIpKSArDQogICAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIHNpemUgPSAibm9uZSIpICsgDQogICAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0zLjUsIDMuNSkpDQoNCg0KZ2dzYXZlKGZpbGUgPSAiZmlnL2xuVlJfcHViX2JpYXNfeWVhci5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA3LCBkcGkgPSA1MDApDQpgYGANCg0KDQojICoqU2Vuc2l0aXZpdHkgYW5hbHlzZXMqKiANCg0KTm90ZSB0aGF0LCBhbHRob3VnaCBtZW50aW9uZWQgaW4gb3VyIHByZS1yZWdpc3RyYXRpb24sIHdlIGRpZCBub3QgY29tcGFyZSBlc3RpbWF0ZXMgZnJvbSBwZWVyLXJldmlld2VkIHB1YmxpY2F0aW9ucyBhbmQgYWNhZGVtaWMgdGhlc2VzLiBUaGlzIGlzIGJlY2F1c2Ugb25seSBhIHNpbmdsZSBpbmNsdWRlZCBzdHVkeSB3YXMgYSB0aGVzaXMuIA0KDQpQcmVwYXJlIGRhdGFzZXQgZm9yIHN1YnNldCBhbmFseXNlcw0KYGBge3J9DQojIEZpbHRlciB0byBvbmx5IHdhcm0gdGVtcGVyYXR1cmVzDQpkYXRhX3dhcm0gPC0gZmlsdGVyKGRhdGEsIHdhcm1fY29sZCA9PSAiV2FybSIpDQoNCiMgRHJvcCB0aXBzIHRoYXQgYXJlIG5vdCBpbiB0aGUgd2FybSBkYXRhc2V0DQp0aXBzX3RvX2Ryb3AgPC0gc2V0ZGlmZihwaHlsb190cmVlJHRpcC5sYWJlbCwgZGF0YV93YXJtJHBoeWxvZ2VueSkNCnBoeWxvX3RyZWVfd2FybSA8LSBkcm9wLnRpcChwaHlsb190cmVlLCB0aXBzX3RvX2Ryb3ApDQoNCiMgQ29tcHV0ZSBwaHlsb2dlbmV0aWMgY29ycmVsYXRpb24gbWF0cml4DQpwaHlsb19tYXRyaXhfd2FybSA8LSB2Y3YocGh5bG9fdHJlZV93YXJtLCBjb3IgPSBUKSAgIyBUaGUgdmN2IGZ1bmN0aW9uIHJldHVybnMgYSB2YXJpYW5jZS1jb3ZhcmlhbmNlIG1hdHJpeA0KDQojIENvbnZlcnQgdGliYmxlIHRvIGRhdGEgZnJhbWUNCmRhdGFfd2FybSA8LSBhcy5kYXRhLmZyYW1lKGRhdGFfd2FybSkNCg0KIyBDYWxjdWxhdGUgVkNWIG1hdHJpeCBmb3IgYWxsIHRocmVlIHJlc3BvbnNlcw0KVkNWX2xuUlJfd2FybSA8LSB2Y2FsYyh2aSA9IHZhcl9sblJSLA0KICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RlciA9IHNoYXJlZF9jb250cm9sX0lELCANCiAgICAgICAgICAgICAgICAgICAgICAgIHJobyA9IDAuNSwNCiAgICAgICAgICAgICAgICAgICAgICAgIG9icyA9IG9icywNCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhX3dhcm0pIA0KDQpWQ1ZfbG5DVlJfd2FybSA8LSB2Y2FsYyh2aSA9IHZhcl9sbkNWUiwNCiAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXIgPSBzaGFyZWRfY29udHJvbF9JRCwgDQogICAgICAgICAgICAgICAgICAgICAgICByaG8gPSAwLjUsDQogICAgICAgICAgICAgICAgICAgICAgICBvYnMgPSBvYnMsDQogICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YV93YXJtKSANCg0KVkNWX2xuVlJfd2FybSA8LSB2Y2FsYyh2aSA9IHZhcl9sblZSLA0KICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RlciA9IHNoYXJlZF9jb250cm9sX0lELCANCiAgICAgICAgICAgICAgICAgICAgICAgIHJobyA9IDAuNSwNCiAgICAgICAgICAgICAgICAgICAgICAgIG9icyA9IG9icywNCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhX3dhcm0pIA0KYGBgDQoNCiMjICoqQ2hhbmdlcyBpbiBtZWFuIHJlc3BvbnNlcyAobG5SUikqKiB7LnRhYnNldCAudGFic2V0X2ZhZGUgLnRhYnNldF9waWxsc30NCg0KIyMjICoqQ29uc3RhbnQgdnMuIGluY3JlYXNpbmcgdGVtcGVyYXR1cmVzKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5SUiB+IDAgKyB0cmFpdF90eXBlOmNvbnN0YW50X2luY3JlYXNpbmcgKyB0cmFpdF90eXBlOmNvbnN0YW50X2luY3JlYXNpbmc6YXNzYXlfdGVtcF9kaWZmICsgIyBTZXBhcmF0ZSBlZmZlY3RzIGJ5IHRyYWl0IHR5cGUNCiAgICAgICAgICAgICAgICAodHJhaXRfdHlwZS0xfHJlZikgKyAjIENvcnJlbGF0aW9uIGJldHdlZW4gdHJhaXRzIGFtb25nIHN0dWRpZXMNCiAgICAgICAgICAgICAgICAoMXxzcGVjaWVzKSArICMgU3BlY2llcy1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8Z3IocGh5bG9nZW55LCBjb3YgPSBwaHlsb19tYXRyaXhfd2FybSkpICsgIyBQaHlsb2dlbmV0aWMgcmVsYXRlZG5lc3MNCiAgICAgICAgICAgICAgICAoMXxleHBlcmltZW50X0lEKSArICMgRXhwZXJpbWVudC1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8b2JzKSArICMgT2JzZXJ2YXRpb24tbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgIGZjb3IoVkNWX2xuUlJfd2FybSkpICMgVmFyaWFuY2UgY292YXJpYW5jZSBtYXRpeCBvZiBjb3JyZWxhdGVkIHNhbXBsaW5nIHZhcmlhbmNlcw0KDQojIERlZmluZSBwcmlvcnMNCnByaW9yID0gYygNCiAgcHJpb3IoY29uc3RhbnQoMSksIGNsYXNzID0gInNpZ21hIikNCikgIyBCZWNhdXNlIHRoZSByZXNpZHVhbCB2YXJpYW5jZS1jb3ZhcmlhbmNlIHN0cnVjdHVyZSBpcyBzcGVjaWZpZWQgaW4gZmNvciwgdGhlcmUgaXMgbm8gbmVlZCB0byBlc3RpbWF0ZSBzaWdtYSBzbyBpdCBpcyBsZWZ0IGFzIGEgY29uc3RhbnQNCg0KIyBGaXQgbW9kZWwNCmxuUlJfbW9kZWxfY29uc3RhbnRfaW5jcmVhc2luZyA8LSBicm0oZm9ybXVsYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBnYXVzc2lhbigpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGFfd2FybSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhMiA9IGxpc3QocGh5bG9fbWF0cml4X3dhcm0gPSBwaHlsb19tYXRyaXhfd2FybSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWQ1ZfbG5SUl93YXJtID0gVkNWX2xuUlJfd2FybSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmlvciA9IHByaW9yLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDQwMDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FybXVwID0gMjAwMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYWlucyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZWQgPSAxMjMpIA0KDQojIFNhdmUgbW9kZWwNCnNhdmVSRFMobG5SUl9tb2RlbF9jb25zdGFudF9pbmNyZWFzaW5nLCBmaWxlID0gIlJEYXRhL2xuUlJfbW9kZWxfY29uc3RhbnRfaW5jcmVhc2luZy5yZHMiKQ0KYGBgDQoNCiMjIyMgKk1vZGVsIG91dHB1dCoNCmBgYHtyfQ0KIyBMb2FkIG1vZGVsDQpsblJSX21vZGVsX2NvbnN0YW50X2luY3JlYXNpbmcgPC0gcmVhZFJEUygiUkRhdGEvbG5SUl9tb2RlbF9jb25zdGFudF9pbmNyZWFzaW5nLnJkcyIpDQoNCiMgRGlzcGxheSBtb2RlbCBvdXRwdXQgDQpzdW1tYXJ5KGxuUlJfbW9kZWxfY29uc3RhbnRfaW5jcmVhc2luZykNCg0KIyBDbGVhbmVkIG1vZGVsIG91dHB1dA0KYXMuZGF0YS5mcmFtZShmaXhlZihsblJSX21vZGVsX2NvbnN0YW50X2luY3JlYXNpbmcsIHN1bW1hcnkgPSBUUlVFKSkgJT4lDQogICMgUmVuYW1lIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBmb3IgY2xlYW5lciBkaXNwbGF5DQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAiUGFyYW1ldGVyIikgJT4lDQogIG11dGF0ZSgNCiAgICAjIFNpbXBsaWZ5IGB0cmFpdF90eXBlYCBhbmQgYGNvbnN0YW50X2luY3JlYXNpbmdgIGludGVyYWN0aW9ucw0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKyk6Y29uc3RhbnRfaW5jcmVhc2luZyhjb25zdGFudHxpbmNyZWFzaW5nKSIsICJcXDEoXFwyKSIsIFBhcmFtZXRlciksDQogICAgIyBBZGp1c3QgZm9yIGFzc2F5X3RlbXBfZGlmZg0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKylcXCgoY29uc3RhbnR8aW5jcmVhc2luZylcXCk6YXNzYXlfdGVtcF9kaWZmIiwgIlxcMShcXDIpOiBhc3NheV90ZW1wX2RpZmYiLCBQYXJhbWV0ZXIpDQogICkgJT4lDQogICMgUm91bmQgbnVtYmVycyB0byAzIGRlY2ltYWwgcG9pbnRzDQogIG11dGF0ZShhY3Jvc3MoYyhFc3RpbWF0ZSwgUTIuNSwgUTk3LjUpLCB+IHJvdW5kKC4sIDMpKSkgJT4lDQogIHNlbGVjdChQYXJhbWV0ZXIsIEVzdGltYXRlLCBgTG93ZXIgQ0lgID0gUTIuNSwgYFVwcGVyIENJYCA9IFE5Ny41KSAlPiUNCiAga2FibGUoKSAlPiUNCiAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImNlbnRlciIsIGZpeGVkX3RoZWFkID0gVFJVRSkgJT4lDQogIGNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFLCBib3JkZXJfcmlnaHQgPSBUUlVFKSAlPiUNCiAgcm93X3NwZWMoMCwgYmFja2dyb3VuZCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIiwgYm9sZCA9IFRSVUUpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZpeGVkX3RoZWFkID0gVFJVRSkNCmBgYA0KDQojIyMjICpDb250cmFzdHMqIA0KYGBge3J9DQojIEdlbmVyYXRlIHByZWRpY3Rpb25zDQplbW1zIDwtIGVtbWVhbnMobG5SUl9tb2RlbF9jb25zdGFudF9pbmNyZWFzaW5nLCANCiAgICAgICAgICAgICAgICBzcGVjcyA9IH4gY29uc3RhbnRfaW5jcmVhc2luZyB8IHRyYWl0X3R5cGUsDQogICAgICAgICAgICAgICAgYXQgPSBsaXN0KGFzc2F5X3RlbXBfZGlmZiA9IDApKQ0KDQojIEdlbmVyYXRlIGNvbnRyYXN0cw0KY29udHJhc3QoZW1tcywgbWV0aG9kID0gInBhaXJ3aXNlIikNCmBgYA0KDQojIyMjICpEYXRhIHZpc3VhbGlzYXRpb24qDQpgYGB7ciwgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQ9MTB9DQojIEdlbmVyYXRlIHByZWRpY3Rpb25zDQplbW1lYW5zX2NvbnN0YW50X2luY3JlYXNpbmcgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKGxuUlJfbW9kZWxfY29uc3RhbnRfaW5jcmVhc2luZywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwZWNzID0gfiBjb25zdGFudF9pbmNyZWFzaW5nIHwgdHJhaXRfdHlwZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXQgPSBsaXN0KGFzc2F5X3RlbXBfZGlmZiA9IDApKSkNCg0KZW1tZWFuc19jb25zdGFudF9pbmNyZWFzaW5nJHRyYWl0X3R5cGUgPC0gZmFjdG9yKGVtbWVhbnNfY29uc3RhbnRfaW5jcmVhc2luZyR0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYm9keV9zaXplIiwgImZlY3VuZGl0eSIsICJzdXJ2aXZhbCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQm9keSBzaXplIiwgIkZlY3VuZGl0eSIsICJTdXJ2aXZhbCIpKQ0KDQplbW1lYW5zX2NvbnN0YW50X2luY3JlYXNpbmckY29uc3RhbnRfaW5jcmVhc2luZyA8LSBmYWN0b3IoZW1tZWFuc19jb25zdGFudF9pbmNyZWFzaW5nJGNvbnN0YW50X2luY3JlYXNpbmcsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb25zdGFudCIsICJpbmNyZWFzaW5nIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJDb25zdGFudCIsICJJbmNyZWFzaW5nIikpDQoNCmRhdGFfd2FybSRjb25zdGFudF9pbmNyZWFzaW5nIDwtIGZhY3RvcihkYXRhX3dhcm0kY29uc3RhbnRfaW5jcmVhc2luZywgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbnN0YW50IiwgImluY3JlYXNpbmciKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbnN0YW50IiwgIkluY3JlYXNpbmciKSkNCg0KDQojIENhbGN1bGF0ZSBzYW1wbGUgc2l6ZXMgYW5kIHN0dWR5IGNvdW50cw0Kc2FtcGxlX3NpemVzX3dhcm0gPC0gZGF0YV93YXJtICU+JQ0KICBncm91cF9ieSh0cmFpdF90eXBlLCBjb25zdGFudF9pbmNyZWFzaW5nKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGVzdGltYXRlcyA9IG4oKSwNCiAgICBzdHVkaWVzID0gbl9kaXN0aW5jdChyZWYpDQogICkNCg0KIyBQbG90DQpnZ3Bsb3QoKSArDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgIyBIb3Jpem9udGFsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSwgDQogICAgICAgICAgICAgICBsd2Q9MSkgKw0KICAgIGdlb21fcXVhc2lyYW5kb20oZGF0YSA9IGRhdGFfd2FybSwgICAgICMgUGxvdCBlZmZlY3Qgc2l6ZXMsIHNjYWxlZCBieSBwcmVjaXNpb24NCiAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTpjb25zdGFudF9pbmNyZWFzaW5nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5SUiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHRyYWl0X3R5cGU6Y29uc3RhbnRfaW5jcmVhc2luZywgDQogICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5SUikpLCANCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsDQogICAgICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMjUsIA0KICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjQ1KSArDQogICAgZ2VvbV9lcnJvcmJhcihkYXRhID0gZW1tZWFuc19jb25zdGFudF9pbmNyZWFzaW5nLCAgIyBQbG90IHRoZSBwb2ludCBlc3RpbWF0ZXMgaW4gd2hpdGUgZm9yIGJhY2tncm91bmQNCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTpjb25zdGFudF9pbmNyZWFzaW5nLCANCiAgICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBEKSwgDQogICAgICAgICAgICAgICAgICBjb2xvcj0id2hpdGUiLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIuNSwNCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4xNykgKw0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGVtbWVhbnNfY29uc3RhbnRfaW5jcmVhc2luZywgICMgUGxvdCB0aGUgY3JlZGlibGUgaW50ZXJ2YWxzIGluIHdoaXRlIGZvciBiYWNrZ3JvdW5kDQogICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6Y29uc3RhbnRfaW5jcmVhc2luZywgDQogICAgICAgICAgICAgICAgICAgeSA9IGVtbWVhbiksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDQsIA0KICAgICAgICAgICAgICAgc3Ryb2tlID0gMiwNCiAgICAgICAgICAgICAgIGNvbG9yPSJ3aGl0ZSIsDQogICAgICAgICAgICAgICBmaWxsID0gIndoaXRlIikgKw0KICAgIGdlb21fZXJyb3JiYXIoZGF0YSA9IGVtbWVhbnNfY29uc3RhbnRfaW5jcmVhc2luZywgIyBQbG90IHRoZSBwb2ludCBlc3RpbWF0ZXMgDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6Y29uc3RhbnRfaW5jcmVhc2luZywgDQogICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCksIA0KICAgICAgICAgICAgICAgICAgY29sb3I9ImJsYWNrIiwNCiAgICAgICAgICAgICAgICAgIHNpemUgPSAyLA0KICAgICAgICAgICAgICAgICAgd2lkdGggPSAwLjE1KSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gZW1tZWFuc19jb25zdGFudF9pbmNyZWFzaW5nLCAjIFBsb3QgdGhlIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOmNvbnN0YW50X2luY3JlYXNpbmcsIA0KICAgICAgICAgICAgICAgICAgIHkgPSBlbW1lYW4pLA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgIHNpemUgPSAzLjUsIA0KICAgICAgICAgICAgICAgc3Ryb2tlID0gMiwNCiAgICAgICAgICAgICAgIGNvbG9yPSJibGFjayIsDQogICAgICAgICAgICAgICBmaWxsID0gIndoaXRlIikgKw0KICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzX3dhcm0sICAjIFNhbXBsZSBzaXplIGFubm90YXRpb25zIA0KICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6Y29uc3RhbnRfaW5jcmVhc2luZywgDQogICAgICAgICAgICAgICAgICB5ID0gMS41LA0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IGNvbnN0YW50X2luY3JlYXNpbmcpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICAgIHRoZW1lX2J3KCkgKyAgICAgIyBDdXN0b21pemUgdGhlIHBsb3QNCiAgICBsYWJzKHkgPSAibG5SUiIsIHggPSAiIikgKw0KICAgIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgOCkpKyANCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjOEU3N0ZGIiwgIiNGRjYwNDAiLCAiIzhFNzdGRiIsICIjRkY2MDQwIiwgIiM4RTc3RkYiLCAiI0ZGNjA0MCIpKSsNCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiQ29uc3RhbnQiID0gIiM4RTc3RkYiLCAiSW5jcmVhc2luZyIgPSAiI0ZGNjA0MCIpKSArICAjIFRleHQgY29sb3VyDQogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpKSArDQogICAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIHNpemUgPSAibm9uZSIpKw0KICAgIGNvb3JkX2ZsaXAoKSArIA0KICAgIHlsaW0oLTEuNSwgMS41KQ0KDQpnZ3NhdmUoZmlsZSA9ICJmaWcvbG5SUl9jb25zdGFudF9pbmNyZWFzaW5nLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIGRwaSA9IDUwMCkNCmBgYA0KDQojIyMgKipMZWF2ZS1vbmUtb3V0IGFuYWx5c2lzKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIEdldCBhIGxpc3Qgb2Ygc3R1ZHkgSURzIGZvciB0aGUgTE9PDQpzdHVkeV9pZHMgPC0gdW5pcXVlKGRhdGEkcmVmKQ0KbnVtX3N0dWRpZXMgPC0gbGVuZ3RoKHN0dWR5X2lkcykNCg0KIyBJbml0aWFsaXplIGEgbGlzdCB0byBzdG9yZSB0aGUgcmVzdWx0cw0KbG9vX3Jlc3VsdHMgPC0gdmVjdG9yKCJsaXN0IiwgbnVtX3N0dWRpZXMpDQpuYW1lcyhsb29fcmVzdWx0cykgPC0gc3R1ZHlfaWRzDQoNCiMgU2V0IHVwIHBhcmFsbGVsIHByb2Nlc3NpbmcgKDE2IG1vZGVscyBhdCBhIHRpbWUpDQpwbGFuKG11bHRpc2Vzc2lvbiwgd29ya2VycyA9IDE2KSAgDQoNCiMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KZm9ybXVsYSA8LSBiZihsblJSIH4gdHJhaXRfdHlwZSAtMSArICMgU2VwYXJhdGUgZWZmZWN0cyBieSB0cmFpdCB0eXBlDQogICAgICAgICAgICAgICAgKHRyYWl0X3R5cGUtMXxyZWYpICsgIyBDb3JyZWxhdGlvbiBiZXR3ZWVuIHRyYWl0cyBhbW9uZyBzdHVkaWVzDQogICAgICAgICAgICAgICAgKDF8c3BlY2llcykgKyAjIFNwZWNpZXMtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfGdyKHBoeWxvZ2VueSwgY292ID0gcGh5bG9fbWF0cml4KSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5SUikpICMgVmFyaWFuY2UgY292YXJpYW5jZSBtYXRpeCBvZiBjb3JyZWxhdGVkIHNhbXBsaW5nIHZhcmlhbmNlcw0KDQojIERlZmluZSBwcmlvcnMNCnByaW9yID0gYygNCiAgcHJpb3IoY29uc3RhbnQoMSksIGNsYXNzID0gInNpZ21hIikNCikgIyBCZWNhdXNlIHRoZSByZXNpZHVhbCB2YXJpYW5jZS1jb3ZhcmlhbmNlIHN0cnVjdHVyZSBpcyBzcGVjaWZpZWQgaW4gZmNvciwgdGhlcmUgaXMgbm8gbmVlZCB0byBlc3RpbWF0ZSBzaWdtYSBzbyBpdCBpcyBsZWZ0IGFzIGEgY29uc3RhbnQNCg0KDQojIEZ1bmN0aW9uIHRvIGZpdCB0aGUgbW9kZWwgYWZ0ZXIgaXRlcmF0aXZlbHkgcmVtb3Zpbmcgb25lIHN0dWR5DQpsZWF2ZV9vbmVfb3V0IDwtIGZ1bmN0aW9uKHN0dWR5X2lkKSB7DQogICMgU3Vic2V0IHRoZSBkYXRhDQogIGRhdGFfc3Vic2V0IDwtIHN1YnNldChkYXRhLCByZWYgIT0gc3R1ZHlfaWQpDQogIA0KICAjIFJlY2FsY3VsYXRlIFZDViBtYXRyaXgNCiAgVkNWX2xuUlJfc3Vic2V0IDwtIHZjYWxjKA0KICAgIHZpID0gdmFyX2xuUlIsDQogICAgY2x1c3RlciA9IHNoYXJlZF9jb250cm9sX0lELCANCiAgICByaG8gPSAwLjUsDQogICAgb2JzID0gb2JzLA0KICAgIGRhdGEgPSBkYXRhX3N1YnNldA0KICApDQogIA0KICAjIEZpdCB0aGUgbW9kZWwNCiAgbW9kZWxfc3Vic2V0IDwtIGJybSgNCiAgICBmb3JtdWxhLCANCiAgICBmYW1pbHkgPSBnYXVzc2lhbigpLA0KICAgIGRhdGEgPSBkYXRhX3N1YnNldCwgDQogICAgZGF0YTIgPSBsaXN0KA0KICAgICAgcGh5bG9fbWF0cml4ID0gcGh5bG9fbWF0cml4LA0KICAgICAgVkNWX2xuUlIgPSBWQ1ZfbG5SUl9zdWJzZXQNCiAgICApLA0KICAgIHByaW9yID0gcHJpb3IsDQogICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTUpLA0KICAgIGl0ZXIgPSAyMDAwLCAjIFJlZHVjZSB0byAyMDAwIGl0ZXJhdGlvbnMgdG8gcmVkdWNlIGNvbXB1dGF0aW9uYWwgZGVtYW5kcw0KICAgIHdhcm11cCA9IDEwMDAsIA0KICAgIGNoYWlucyA9IDIsICMgT25seSB0d28gY2hhaW5zIHRvIHJlZHVjZSBjb21wdXRhdGlvbmFsIGRlbWFuZHMNCiAgICBjb3JlcyA9IDEsICAgIyBTZXQgY29yZXMgdG8gMSBpbnNpZGUgdGhlIGZ1bmN0aW9uDQogICAgc2VlZCA9IDEyMw0KICApDQoNCiAgIyBFeHRyYWN0IHRoZSBmaXhlZCBlZmZlY3RzDQogIGZpeGVkX2VmZmVjdHMgPC0gZml4ZWYobW9kZWxfc3Vic2V0KQ0KICANCiAgIyBSZXR1cm4gdGhlIGZpeGVkIGVmZmVjdHMNCiAgcmV0dXJuKGxpc3Qoc3R1ZHlfaWQgPSBzdHVkeV9pZCwgZml4ZWRfZWZmZWN0cyA9IGZpeGVkX2VmZmVjdHMpKQ0KfQ0KDQojIFJ1biB0aGUgZnVuY3Rpb24gaW4gcGFyYWxsZWwgb3ZlciB0aGUgc3R1ZGllcw0KbG9vX3Jlc3VsdHMgPC0gZnV0dXJlX2xhcHBseShzdHVkeV9pZHMsIGxlYXZlX29uZV9vdXQpDQoNCiMgU2F2ZSByZXN1bHRzDQpzYXZlUkRTKGxvb19yZXN1bHRzLCBmaWxlID0gIlJEYXRhL2xuUlJfTE9PX3Jlc3VsdHMucmRzIikNCmBgYA0KDQojIyMjICpNb2RlbCBzdW1tYXJ5Kg0KYGBge3J9DQojIExvYWQgdGhlIGxpc3Qgb2YgYWxsIG1vZGVsIG91dHB1dHMNCmxvb19sblJSIDwtIHJlYWRSRFMoZmlsZSA9ICJSRGF0YS9sblJSX0xPT19yZXN1bHRzLnJkcyIpIA0KDQojIEV4dHJhY3QgZGF0YSBvbiBmaXhlZCBlZmZlY3RzIGZyb20gZWFjaCBtb2RlbA0KDQpsb29fcmVzdWx0c19sblJSIDwtIGRvLmNhbGwocmJpbmQsIGxhcHBseShsb29fbG5SUiwgZnVuY3Rpb24oeCkgew0KICAjIEV4dHJhY3Qgc3R1ZHlfaWQgYW5kIGZpeGVkX2VmZmVjdHMgZGF0YQ0KICBzdHVkeV9pZCA8LSB4JHN0dWR5X2lkDQogIGZpeGVkX2VmZmVjdHMgPC0geCRmaXhlZF9lZmZlY3RzDQogIA0KICAjIENvbnZlcnQgcm93IG5hbWVzICh0cmFpdF90eXBlKSB0byBhIGNvbHVtbiwgcmVtb3ZlIHByZWZpeCwgYW5kIGFkZCBzdHVkeV9pZA0KICBmaXhlZF9lZmZlY3RzIDwtIGRhdGEuZnJhbWUodHJhaXRfdHlwZSA9IHN1YigidHJhaXRfdHlwZSIsICIiLCByb3duYW1lcyhmaXhlZF9lZmZlY3RzKSksIGZpeGVkX2VmZmVjdHMpDQogIGZpeGVkX2VmZmVjdHMkc3R1ZHlfaWQgPC0gc3R1ZHlfaWQNCiAgDQogICMgUmVtb3ZlIHJvdyBuYW1lcw0KICByb3duYW1lcyhmaXhlZF9lZmZlY3RzKSA8LSBOVUxMDQogIA0KICByZXR1cm4oZml4ZWRfZWZmZWN0cykNCn0pKQ0KDQpsb29fcmVzdWx0c19sblJSJHRyYWl0X3R5cGUgPC0gZmFjdG9yKGxvb19yZXN1bHRzX2xuUlIkdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KIyBTdW1tYXJpc2UgdGhlIGRhdGENCmxvb19yZXN1bHRzX2xuUlIgJT4lIA0KICBncm91cF9ieSh0cmFpdF90eXBlKSAlPiUgDQogIHN1bW1hcmlzZShFc3RpbWF0ZSA9IG1lYW4oRXN0aW1hdGUpLA0KICAgICAgICAgICAgU0UgPSBtZWFuKEVzdC5FcnJvciksIA0KICAgICAgICAgICAgbG93ZXJfQ0kgPSBtZWFuKFEyLjUpLA0KICAgICAgICAgICAgdXBwZXJfQ0kgPSBtZWFuKFE5Ny41KSkgIyBNZWFuIGFjcm9zcyBhbGwgbW9kZWxzDQpgYGANCg0KIyMjIyAqRGF0YSB2aXN1YWxpc2F0aW9uKiANCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD0xNX0NCiMgUGxvdA0KZ2dwbG90KCkgKw0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUsIA0KICAgICAgICAgICAgICAgbHdkPTEpICsNCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBsb29fcmVzdWx0c19sblJSLCAgIyBQbG90IHRoZSBjcmVkaWJsZSBpbnRlcnZhbHMgaW4gd2hpdGUgZm9yIGJhY2tncm91bmQNCiAgICAgICAgICAgICAgIGFlcyh4ID0gc3R1ZHlfaWQsIA0KICAgICAgICAgICAgICAgICAgIHkgPSBFc3RpbWF0ZSwNCiAgICAgICAgICAgICAgICAgICB5bWluID0gUTIuNSwgDQogICAgICAgICAgICAgICAgICAgeW1heCA9IFE5Ny41LA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gdHJhaXRfdHlwZSksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDEsDQogICAgICAgICAgICAgICB3aWR0aCA9IDAuMykgKw0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGxvb19yZXN1bHRzX2xuUlIsDQogICAgICAgICAgICAgICBhZXMoeCA9IHN0dWR5X2lkLCANCiAgICAgICAgICAgICAgICAgICB5ID0gRXN0aW1hdGUsDQogICAgICAgICAgICAgICAgICAgZmlsbCA9IHRyYWl0X3R5cGUpLA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgIHNpemUgPSA0LCANCiAgICAgICAgICAgICAgIHN0cm9rZSA9IDEsDQogICAgICAgICAgICAgICBjb2xvcj0iYmxhY2siKSArDQogICAgdGhlbWVfYncoKSArICAgICAjIEN1c3RvbWl6ZSB0aGUgcGxvdA0KICAgIGxhYnMoeSA9ICJsblJSIiwgeCA9ICIiKSArDQogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzczQjcwNiIsICIjMDZBMkJBIiwgIiNCOTA2NzQiKSkrDQogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiM3M0I3MDYiLCAiIzA2QTJCQSIsICIjQjkwNjc0IikpICsgIA0KICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNCksDQogICAgICAgICAgYXhpcy50ZXh0LnkgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDEwLCANCiAgICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCBoanVzdCA9IDAuNSksDQogICAgICAgICAgYXhpcy50ZXh0LnggPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIwKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvciA9ICJub25lIikrDQogICAgY29vcmRfZmxpcCgpKw0KICAgIHhsaW0oLTAuMTUsIDAuMTUpICsNCiAgICBmYWNldF93cmFwKH50cmFpdF90eXBlLCBuY29sID0gMykrDQogICAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSByZXYobGV2ZWxzKGFzLmZhY3Rvcihsb29fcmVzdWx0c19sblJSJHN0dWR5X2lkKSkpKSAjIEFscGhhYmV0aWNhbCBvcmRlcg0KDQpnZ3NhdmUoZmlsZSA9ICJmaWcvbG5SUl9MT08ucG5nIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gMTIsIGRwaSA9IDUwMCkNCmBgYA0KDQoNCiMjIyAqKlVudXN1YWwgc3R1ZHkgZGVzaWducyoqIA0KDQojIyMjICpNb2RlbCBzcGVjaWZpY2F0aW9uKg0KYGBge3IsIGV2YWwgPSBGfQ0KIyBEaXNjYXJkIG9ic2VydmF0aW9ucyBmbGFnZ2VkIGJlY2F1c2UgdGhlIG51bWJlciBvZiBnZW5lcmF0aW9ucyBvZiBzZWxlY3Rpb24gd2FzIHVuY2xlYXIsIGFzIHRoaXMgd291bGQgb25seSBhZmZlY3QgdGhlIHJlc3VsdHMgb2YgbWV0YS1yZWdyZXNzaW9ucw0KZGF0YSA8LSBtdXRhdGUoZGF0YSwgbWlub3JfY29uY2VybnMyID0gaWZlbHNlKG1pbm9yX2NvbmNlcm5zID09ICJnZW5fc2VsZWN0aW9uIGFwcHJveGltYXRlIiB8IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5vcl9jb25jZXJucyA9PSAiZ2VuX3NlbGVjdGlvbiB1bmRlcmVzdGltYXRlZCIsDQogICAgICAgICAgICAgICAgICAgICBOQSwgbWlub3JfY29uY2VybnMpKSANCg0KIyBGaWx0ZXIgdG8gZGF0YSB3aXRob3V0IHNvdXJjZXMgb2YgcHJvY2VkdXJhbCAgY29uY2VybnMuDQpkYXRhX2NvbmNlcm5zIDwtIGZpbHRlcihkYXRhLCBpcy5uYShtYWpvcl9jb25jZXJucyk9PVQgJiBpcy5uYShtaW5vcl9jb25jZXJuczIpPT1UKQ0KDQojIERyb3AgdGlwcyB0aGF0IGFyZSBub3QgaW4gdGhlIHdhcm0gZGF0YXNldA0KdGlwc190b19kcm9wIDwtIHNldGRpZmYocGh5bG9fdHJlZSR0aXAubGFiZWwsIGRhdGFfY29uY2VybnMkcGh5bG9nZW55KQ0KcGh5bG9fdHJlZV9jb25jZXJucyA8LSBkcm9wLnRpcChwaHlsb190cmVlLCB0aXBzX3RvX2Ryb3ApDQoNCiMgQ29tcHV0ZSBwaHlsb2dlbmV0aWMgY29ycmVsYXRpb24gbWF0cml4DQpwaHlsb19tYXRyaXhfY29uY2VybnMgPC0gdmN2KHBoeWxvX3RyZWVfY29uY2VybnMsIGNvciA9IFQpICAjIFRoZSB2Y3YgZnVuY3Rpb24gcmV0dXJucyBhIHZhcmlhbmNlLWNvdmFyaWFuY2UgbWF0cml4DQoNCiMgQ29udmVydCB0aWJibGUgdG8gZGF0YSBmcmFtZQ0KZGF0YV9jb25jZXJucyA8LSBhcy5kYXRhLmZyYW1lKGRhdGFfY29uY2VybnMpDQoNCiMgQ2FsY3VsYXRlIFZDViBtYXRyaXgNClZDVl9sblJSX2NvbmNlcm5zIDwtIHZjYWxjKHZpID0gdmFyX2xuUlIsDQogICAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXIgPSBzaGFyZWRfY29udHJvbF9JRCwgDQogICAgICAgICAgICAgICAgICAgICAgIHJobyA9IDAuNSwNCiAgICAgICAgICAgICAgICAgICAgICAgb2JzID0gb2JzLA0KICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YV9jb25jZXJucykgDQoNCiMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KZm9ybXVsYSA8LSBiZihsblJSIH4gMCArIHRyYWl0X3R5cGU6d2FybV9jb2xkICsgdHJhaXRfdHlwZTp3YXJtX2NvbGQ6YXNzYXlfdGVtcF9kaWZmICsgIyBTZXBhcmF0ZSBlZmZlY3RzIGJ5IHRyYWl0IHR5cGUNCiAgICAgICAgICAgICAgICAodHJhaXRfdHlwZS0xfHJlZikgKyAjIENvcnJlbGF0aW9uIGJldHdlZW4gdHJhaXRzIGFtb25nIHN0dWRpZXMNCiAgICAgICAgICAgICAgICAoMXxzcGVjaWVzKSArICMgU3BlY2llcy1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8Z3IocGh5bG9nZW55LCBjb3YgPSBwaHlsb19tYXRyaXhfY29uY2VybnMpKSArICMgUGh5bG9nZW5ldGljIHJlbGF0ZWRuZXNzDQogICAgICAgICAgICAgICAgKDF8ZXhwZXJpbWVudF9JRCkgKyAjIEV4cGVyaW1lbnQtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfG9icykgKyAjIE9ic2VydmF0aW9uLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICBmY29yKFZDVl9sblJSX2NvbmNlcm5zKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5SUl9tb2RlbF9jb25jZXJucyA8LSBicm0oZm9ybXVsYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IGdhdXNzaWFuKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhX2NvbmNlcm5zLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTIgPSBsaXN0KHBoeWxvX21hdHJpeF9jb25jZXJucyA9IHBoeWxvX21hdHJpeF9jb25jZXJucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZDVl9sblJSX2NvbmNlcm5zID0gVkNWX2xuUlJfY29uY2VybnMpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmlvciA9IHByaW9yLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXIgPSA0MDAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FybXVwID0gMjAwMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhaW5zID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZWQgPSAxMjMpIA0KIyBTYXZlIG1vZGVsDQpzYXZlUkRTKGxuUlJfbW9kZWxfY29uY2VybnMsIGZpbGUgPSAiUkRhdGEvbG5SUl9tb2RlbF9jb25jZXJucy5yZHMiKQ0KYGBgDQoNCiMjIyMgKk1vZGVsIHN1bW1hcnkqDQpgYGB7cn0NCiMgTG9hZCBtb2RlbA0KbG5SUl9tb2RlbF9jb25jZXJucyA8LSByZWFkUkRTKCJSRGF0YS9sblJSX21vZGVsX2NvbmNlcm5zLnJkcyIpDQoNCiMgRGlzcGxheSBtb2RlbCBvdXRwdXQgDQpzdW1tYXJ5KGxuUlJfbW9kZWxfY29uY2VybnMpDQoNCiMgQ2xlYW5lZCBtb2RlbCBvdXRwdXQNCmFzLmRhdGEuZnJhbWUoZml4ZWYobG5SUl9tb2RlbF9jb25jZXJucywgc3VtbWFyeSA9IFRSVUUpKSAlPiUNCiAgIyBSZW5hbWUgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGZvciBjbGVhbmVyIGRpc3BsYXkNCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJQYXJhbWV0ZXIiKSAlPiUgDQogIG11dGF0ZSgNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspOndhcm1fY29sZChjb2xkfHdhcm0pIiwgIlxcMShcXDIpIiwgUGFyYW1ldGVyKSwNCiAgICBQYXJhbWV0ZXIgPSBnc3ViKCJ0cmFpdF90eXBlKFthLXpfXSspXFwod2FybVxcKTphc3NheV90ZW1wX2RpZmYiLCAiXFwxKHdhcm0pOiBhc3NheV90ZW1wX2RpZmYiLCBQYXJhbWV0ZXIpDQogICkgJT4lDQogICMgUm91bmQgbnVtYmVycyB0byAzIGRlY2ltYWwgcG9pbnRzDQogIG11dGF0ZShhY3Jvc3MoYyhFc3RpbWF0ZSwgUTIuNSwgUTk3LjUpLCB+IHJvdW5kKC4sIDMpKSkgJT4lDQogIHNlbGVjdChQYXJhbWV0ZXIsIEVzdGltYXRlLCBgTG93ZXIgQ0lgID0gUTIuNSwgYFVwcGVyIENJYCA9IFE5Ny41KSAlPiUNCiAga2FibGUoKSAlPiUNCiAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImNlbnRlciIsIGZpeGVkX3RoZWFkID0gVFJVRSkgJT4lDQogIGNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFLCBib3JkZXJfcmlnaHQgPSBUUlVFKSAlPiUNCiAgcm93X3NwZWMoMCwgYmFja2dyb3VuZCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIiwgYm9sZCA9IFRSVUUpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZpeGVkX3RoZWFkID0gVFJVRSkNCmBgYA0KDQojIyMjICpEYXRhIHZpc3VhbGlzYXRpb24qIA0KYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0PTEwfQ0KIyBEaXNjYXJkIG9ic2VydmF0aW9ucyBmbGFnZ2VkIGJlY2F1c2UgdGhlIG51bWJlciBvZiBnZW5lcmF0aW9ucyBvZiBzZWxlY3Rpb24gd2FzIHVuY2xlYXIsIGFzIHRoaXMgd291bGQgb25seSBhZmZlY3QgdGhlIHJlc3VsdHMgb2YgbWV0YS1yZWdyZXNzaW9ucw0KZGF0YSA8LSBtdXRhdGUoZGF0YSwgbWlub3JfY29uY2VybnMyID0gaWZlbHNlKG1pbm9yX2NvbmNlcm5zID09ICJnZW5fc2VsZWN0aW9uIGFwcHJveGltYXRlIiB8IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5vcl9jb25jZXJucyA9PSAiZ2VuX3NlbGVjdGlvbiB1bmRlcmVzdGltYXRlZCIsDQogICAgICAgICAgICAgICAgICAgICBOQSwgbWlub3JfY29uY2VybnMpKSANCg0KIyBGaWx0ZXIgdG8gZGF0YSB3aXRob3V0IHNvdXJjZXMgb2YgcHJvY2VkdXJhbCAgY29uY2VybnMuDQpkYXRhX2NvbmNlcm5zIDwtIGZpbHRlcihkYXRhLCBpcy5uYShtYWpvcl9jb25jZXJucyk9PVQgJiBpcy5uYShtaW5vcl9jb25jZXJuczIpPT1UKQ0KDQojIENhbGN1bGF0ZSBzYW1wbGUgc2l6ZXMgYW5kIHN0dWR5IGNvdW50cw0Kc2FtcGxlX3NpemVzX2NvbmNlcm5zIDwtIGRhdGFfY29uY2VybnMgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBlc3RpbWF0ZXMgPSBuKCksDQogICAgc3R1ZGllcyA9IG5fZGlzdGluY3QocmVmKQ0KICApDQoNCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbWVhbnNfY29uY2VybnMgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsblJSX21vZGVsX2NvbmNlcm5zLA0KICBzcGVjcyA9IH4gYXNzYXlfdGVtcF9kaWZmIHwgdHJhaXRfdHlwZSAqIHdhcm1fY29sZCwNCiAgYXQgPSBsaXN0KGFzc2F5X3RlbXBfZGlmZiA9IHNlcShtaW4oZGF0YV9jb25jZXJucyRhc3NheV90ZW1wX2RpZmYpLCBtYXgoZGF0YV9jb25jZXJucyRhc3NheV90ZW1wX2RpZmYpLCBieSA9IDAuNSkpKQ0KICApDQoNCiMgQ2FsY3VsYXRlIHJhbmdlIG9mIHZhbHVlcyBmb3IgZWFjaCBjYXRlZ29yeQ0KcmFuZ2VfZGZfY29uY2VybnMgPC0gZGF0YV9jb25jZXJucyAlPiUNCiAgZ3JvdXBfYnkodHJhaXRfdHlwZSwgd2FybV9jb2xkKSAlPiUNCiAgc3VtbWFyaXplKA0KICAgIG1pbl9hc3NheV90ZW1wX2RpZmYgPSBtaW4oYXNzYXlfdGVtcF9kaWZmKSwNCiAgICBtYXhfYXNzYXlfdGVtcF9kaWZmID0gbWF4KGFzc2F5X3RlbXBfZGlmZikNCiAgKQ0KDQplbW1lYW5zX2NvbmNlcm5zJHRyYWl0X3R5cGUgPC0gZmFjdG9yKGVtbWVhbnNfY29uY2VybnMkdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KZW1tZWFuc19jb25jZXJucyR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfY29uY2VybnMkd2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiY29sZCIsICJ3YXJtIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJDb2xkIiwgIldhcm0iKSkNCg0KIyBUYWlsb3IgcHJlZGljdGlvbnMgdG8gdGhlIHJhbmdlIG9mIHRoZSBkYXRhDQplbW1lYW5zX2NvbmNlcm5zIDwtIGVtbWVhbnNfY29uY2VybnMgJT4lDQogIGxlZnRfam9pbihyYW5nZV9kZl9jb25jZXJucywgYnkgPSBjKCJ0cmFpdF90eXBlIiwgIndhcm1fY29sZCIpKSAlPiUNCiAgZmlsdGVyKA0KICAgIGFzc2F5X3RlbXBfZGlmZiA+PSBtaW5fYXNzYXlfdGVtcF9kaWZmLA0KICAgIGFzc2F5X3RlbXBfZGlmZiA8PSBtYXhfYXNzYXlfdGVtcF9kaWZmDQogICkNCg0KIyBQbG90DQpnZ3Bsb3QoKSArIA0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUpICsgIA0KICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsICMgVmVydGljYWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGFfY29uY2VybnMsICMgRWZmZWN0IHNpemVzLCBzY2FsZWQgYnkgcHJlY2lzaW9uDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IGFzc2F5X3RlbXBfZGlmZiwgDQogICAgICAgICAgICAgICAgICAgICAgeSA9IGxuUlIsIA0KICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxL3NxcnQodmFyX2xuUlIpLCANCiAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgICBzaGFwZSA9IDIxLCANCiAgICAgICAgICAgICAgICAgIGFscGhhID0gMC43LCANCiAgICAgICAgICAgICAgICAgIHN0cm9rZSA9IDEsDQogICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IDAuMDUpKSArIA0KICAgICBnZW9tX3JpYmJvbihkYXRhID0gZW1tZWFuc19jb25jZXJucywgIyBTaGFkZWQgYXJlYSBmb3IgY3JlZGlibGUgaW50ZXJ2YWxzDQogICAgICAgICAgICAgICAgIGFlcyh4ID0gYXNzYXlfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICBhbHBoYSA9IC41KSArIA0KICAgICBnZW9tX2xpbmUoZGF0YSA9IGVtbWVhbnNfY29uY2VybnMsICAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSBhc3NheV90ZW1wX2RpZmYsDQogICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsgDQogICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXNfY29uY2VybnMsIA0KICAgICAgICAgICAgICBhZXMoeCA9IEluZiwgDQogICAgICAgICAgICAgICAgICB5ID0gaWZlbHNlKHdhcm1fY29sZCA9PSAiV2FybSIsIC0wLjksIC0xLjMpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICANCiAgZmFjZXRfd3JhcCh+IHRyYWl0X3R5cGUsIG5jb2wgPSAxKSArICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJBc3NheSB0ZW1wZXJhdHVyZSBkaWZmZXJlbmNlIiwgeSA9ICJsblJSIiwNCiAgICAgICBjb2wgPSAiUmVnaW1lIikgKw0KICB0aGVtZV9idygpICsgDQogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgOCkpKyANCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjUsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxOCksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAyMikpICsNCiAgICBndWlkZXMoZmlsbCA9ICJub25lIiwgc2l6ZSA9ICJub25lIikrDQogICAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0xLjUsIDEuNSkpDQoNCmdnc2F2ZShmaWxlID0gImZpZy9sblJSX2NvbmNlcm5zLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIGRwaSA9IDUwMCkNCmBgYA0KDQoNCiMjICoqQ2hhbmdlcyBpbiByZWxhdGl2ZSB0cmFpdCB2YXJpYW5jZSAobG5DVlIpKiogey50YWJzZXQgLnRhYnNldF9mYWRlIC50YWJzZXRfcGlsbHN9DQoNCiMjIyAqKkNvbnN0YW50IHZzLiBpbmNyZWFzaW5nIHRlbXBlcmF0dXJlcyoqIA0KDQojIyMjICpNb2RlbCBzcGVjaWZpY2F0aW9uKg0KYGBge3IsIGV2YWwgPSBGfQ0KIyBNb2RlbCBzcGVjaWZpY2F0aW9uDQpmb3JtdWxhIDwtIGJmKGxuQ1ZSIH4gMCArIHRyYWl0X3R5cGU6Y29uc3RhbnRfaW5jcmVhc2luZyArIHRyYWl0X3R5cGU6Y29uc3RhbnRfaW5jcmVhc2luZzphc3NheV90ZW1wX2RpZmYgKyAjIFNlcGFyYXRlIGVmZmVjdHMgYnkgdHJhaXQgdHlwZQ0KICAgICAgICAgICAgICAgICh0cmFpdF90eXBlLTF8cmVmKSArICMgQ29ycmVsYXRpb24gYmV0d2VlbiB0cmFpdHMgYW1vbmcgc3R1ZGllcw0KICAgICAgICAgICAgICAgICgxfHNwZWNpZXMpICsgIyBTcGVjaWVzLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxncihwaHlsb2dlbnksIGNvdiA9IHBoeWxvX21hdHJpeF93YXJtKSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5DVlJfd2FybSkpICMgVmFyaWFuY2UgY292YXJpYW5jZSBtYXRpeCBvZiBjb3JyZWxhdGVkIHNhbXBsaW5nIHZhcmlhbmNlcw0KDQojIERlZmluZSBwcmlvcnMNCnByaW9yID0gYygNCiAgcHJpb3IoY29uc3RhbnQoMSksIGNsYXNzID0gInNpZ21hIikNCikgIyBCZWNhdXNlIHRoZSByZXNpZHVhbCB2YXJpYW5jZS1jb3ZhcmlhbmNlIHN0cnVjdHVyZSBpcyBzcGVjaWZpZWQgaW4gZmNvciwgdGhlcmUgaXMgbm8gbmVlZCB0byBlc3RpbWF0ZSBzaWdtYSBzbyBpdCBpcyBsZWZ0IGFzIGEgY29uc3RhbnQNCg0KIyBGaXQgbW9kZWwNCmxuQ1ZSX21vZGVsX2NvbnN0YW50X2luY3JlYXNpbmcgPC0gYnJtKGZvcm11bGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gZ2F1c3NpYW4oKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhX3dhcm0sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTIgPSBsaXN0KHBoeWxvX21hdHJpeF93YXJtID0gcGh5bG9fbWF0cml4X3dhcm0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVkNWX2xuQ1ZSX3dhcm0gPSBWQ1ZfbG5DVlJfd2FybSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmlvciA9IHByaW9yLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDQwMDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FybXVwID0gMjAwMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYWlucyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZWQgPSAxMjMpIA0KDQojIFNhdmUgbW9kZWwNCnNhdmVSRFMobG5DVlJfbW9kZWxfY29uc3RhbnRfaW5jcmVhc2luZywgZmlsZSA9ICJSRGF0YS9sbkNWUl9tb2RlbF9jb25zdGFudF9pbmNyZWFzaW5nLnJkcyIpDQpgYGANCg0KIyMjIyAqTW9kZWwgb3V0cHV0Kg0KYGBge3J9DQojIExvYWQgbW9kZWwNCmxuQ1ZSX21vZGVsX2NvbnN0YW50X2luY3JlYXNpbmcgPC0gcmVhZFJEUygiUkRhdGEvbG5DVlJfbW9kZWxfY29uc3RhbnRfaW5jcmVhc2luZy5yZHMiKQ0KDQojIERpc3BsYXkgbW9kZWwgb3V0cHV0IA0Kc3VtbWFyeShsbkNWUl9tb2RlbF9jb25zdGFudF9pbmNyZWFzaW5nKQ0KDQojIENsZWFuZWQgbW9kZWwgb3V0cHV0DQphcy5kYXRhLmZyYW1lKGZpeGVmKGxuQ1ZSX21vZGVsX2NvbnN0YW50X2luY3JlYXNpbmcsIHN1bW1hcnkgPSBUUlVFKSkgJT4lDQogICMgUmVuYW1lIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBmb3IgY2xlYW5lciBkaXNwbGF5DQogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAiUGFyYW1ldGVyIikgJT4lDQogIG11dGF0ZSgNCiAgICAjIFNpbXBsaWZ5IGB0cmFpdF90eXBlYCBhbmQgYGNvbnN0YW50X2luY3JlYXNpbmdgIGludGVyYWN0aW9ucw0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKyk6Y29uc3RhbnRfaW5jcmVhc2luZyhjb25zdGFudHxpbmNyZWFzaW5nKSIsICJcXDEoXFwyKSIsIFBhcmFtZXRlciksDQogICAgIyBBZGp1c3QgZm9yIGFzc2F5X3RlbXBfZGlmZg0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKylcXCgoY29uc3RhbnR8aW5jcmVhc2luZylcXCk6YXNzYXlfdGVtcF9kaWZmIiwgIlxcMShcXDIpOiBhc3NheV90ZW1wX2RpZmYiLCBQYXJhbWV0ZXIpDQogICkgJT4lDQogICMgUm91bmQgbnVtYmVycyB0byAzIGRlY2ltYWwgcG9pbnRzDQogIG11dGF0ZShhY3Jvc3MoYyhFc3RpbWF0ZSwgUTIuNSwgUTk3LjUpLCB+IHJvdW5kKC4sIDMpKSkgJT4lDQogIHNlbGVjdChQYXJhbWV0ZXIsIEVzdGltYXRlLCBgTG93ZXIgQ0lgID0gUTIuNSwgYFVwcGVyIENJYCA9IFE5Ny41KSAlPiUNCiAga2FibGUoKSAlPiUNCiAga2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImNlbnRlciIsIGZpeGVkX3RoZWFkID0gVFJVRSkgJT4lDQogIGNvbHVtbl9zcGVjKDEsIGJvbGQgPSBUUlVFLCBib3JkZXJfcmlnaHQgPSBUUlVFKSAlPiUNCiAgcm93X3NwZWMoMCwgYmFja2dyb3VuZCA9ICJ3aGl0ZSIsIGNvbG9yID0gImJsYWNrIiwgYm9sZCA9IFRSVUUpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZpeGVkX3RoZWFkID0gVFJVRSkNCmBgYA0KDQojIyMjICpDb250cmFzdHMqIA0KYGBge3J9DQojIEdlbmVyYXRlIHByZWRpY3Rpb25zDQplbW1zIDwtIGVtbWVhbnMobG5DVlJfbW9kZWxfY29uc3RhbnRfaW5jcmVhc2luZywgDQogICAgICAgICAgICAgICAgc3BlY3MgPSB+IGNvbnN0YW50X2luY3JlYXNpbmcgfCB0cmFpdF90eXBlLA0KICAgICAgICAgICAgICAgIGF0ID0gbGlzdChhc3NheV90ZW1wX2RpZmYgPSAwKSkNCg0KIyBHZW5lcmF0ZSBjb250cmFzdHMNCmNvbnRyYXN0KGVtbXMsIG1ldGhvZCA9ICJwYWlyd2lzZSIpDQpgYGANCg0KIyMjIyAqRGF0YSB2aXN1YWxpc2F0aW9uKg0KYGBge3IsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0PTEwfQ0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucw0KZW1tZWFuc19jb25zdGFudF9pbmNyZWFzaW5nIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucyhsbkNWUl9tb2RlbF9jb25zdGFudF9pbmNyZWFzaW5nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlY3MgPSB+IGNvbnN0YW50X2luY3JlYXNpbmcgfCB0cmFpdF90eXBlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdCA9IGxpc3QoYXNzYXlfdGVtcF9kaWZmID0gMCkpKQ0KDQplbW1lYW5zX2NvbnN0YW50X2luY3JlYXNpbmckdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19jb25zdGFudF9pbmNyZWFzaW5nJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfY29uc3RhbnRfaW5jcmVhc2luZyRjb25zdGFudF9pbmNyZWFzaW5nIDwtIGZhY3RvcihlbW1lYW5zX2NvbnN0YW50X2luY3JlYXNpbmckY29uc3RhbnRfaW5jcmVhc2luZywgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbnN0YW50IiwgImluY3JlYXNpbmciKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbnN0YW50IiwgIkluY3JlYXNpbmciKSkNCg0KIyBQbG90DQpnZ3Bsb3QoKSArDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgIyBIb3Jpem9udGFsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSwgDQogICAgICAgICAgICAgICBsd2Q9MSkgKw0KICAgIGdlb21fcXVhc2lyYW5kb20oZGF0YSA9IGRhdGFfd2FybSwgICAgICMgUGxvdCBlZmZlY3Qgc2l6ZXMsIHNjYWxlZCBieSBwcmVjaXNpb24NCiAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTpjb25zdGFudF9pbmNyZWFzaW5nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5DVlIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB0cmFpdF90eXBlOmNvbnN0YW50X2luY3JlYXNpbmcsIA0KICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxL3NxcnQodmFyX2xuQ1ZSKSksIA0KICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLA0KICAgICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4yNSwgDQogICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNDUpICsNCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBlbW1lYW5zX2NvbnN0YW50X2luY3JlYXNpbmcsICAjIFBsb3QgdGhlIHBvaW50IGVzdGltYXRlcyBpbiB3aGl0ZSBmb3IgYmFja2dyb3VuZA0KICAgICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOmNvbnN0YW50X2luY3JlYXNpbmcsIA0KICAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQpLCANCiAgICAgICAgICAgICAgICAgIGNvbG9yPSJ3aGl0ZSIsDQogICAgICAgICAgICAgICAgICBzaXplID0gMi41LA0KICAgICAgICAgICAgICAgICAgd2lkdGggPSAwLjE3KSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gZW1tZWFuc19jb25zdGFudF9pbmNyZWFzaW5nLCAgIyBQbG90IHRoZSBjcmVkaWJsZSBpbnRlcnZhbHMgaW4gd2hpdGUgZm9yIGJhY2tncm91bmQNCiAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTpjb25zdGFudF9pbmNyZWFzaW5nLCANCiAgICAgICAgICAgICAgICAgICB5ID0gZW1tZWFuKSwNCiAgICAgICAgICAgICAgIHNoYXBlID0gMjEsDQogICAgICAgICAgICAgICBzaXplID0gNCwgDQogICAgICAgICAgICAgICBzdHJva2UgPSAyLA0KICAgICAgICAgICAgICAgY29sb3I9IndoaXRlIiwNCiAgICAgICAgICAgICAgIGZpbGwgPSAid2hpdGUiKSArDQogICAgZ2VvbV9lcnJvcmJhcihkYXRhID0gZW1tZWFuc19jb25zdGFudF9pbmNyZWFzaW5nLCAjIFBsb3QgdGhlIHBvaW50IGVzdGltYXRlcyANCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTpjb25zdGFudF9pbmNyZWFzaW5nLCANCiAgICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBEKSwgDQogICAgICAgICAgICAgICAgICBjb2xvcj0iYmxhY2siLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIsDQogICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMTUpICsNCiAgICBnZW9tX3BvaW50KGRhdGEgPSBlbW1lYW5zX2NvbnN0YW50X2luY3JlYXNpbmcsICMgUGxvdCB0aGUgY3JlZGlibGUgaW50ZXJ2YWxzDQogICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6Y29uc3RhbnRfaW5jcmVhc2luZywgDQogICAgICAgICAgICAgICAgICAgeSA9IGVtbWVhbiksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDMuNSwgDQogICAgICAgICAgICAgICBzdHJva2UgPSAyLA0KICAgICAgICAgICAgICAgY29sb3I9ImJsYWNrIiwNCiAgICAgICAgICAgICAgIGZpbGwgPSAid2hpdGUiKSArDQogICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXNfd2FybSwgICMgU2FtcGxlIHNpemUgYW5ub3RhdGlvbnMgDQogICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTpjb25zdGFudF9pbmNyZWFzaW5nLCANCiAgICAgICAgICAgICAgICAgIHkgPSAzLA0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IGNvbnN0YW50X2luY3JlYXNpbmcpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICAgIHRoZW1lX2J3KCkgKyAgICAgIyBDdXN0b21pemUgdGhlIHBsb3QNCiAgICBsYWJzKHkgPSAibG5DVlIiLCB4ID0gIiIpICsNCiAgICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDIsIDgpKSsgDQogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzhFNzdGRiIsICIjRkY2MDQwIiwgIiM4RTc3RkYiLCAiI0ZGNjA0MCIsICIjOEU3N0ZGIiwgIiNGRjYwNDAiKSkrDQogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIkNvbnN0YW50IiA9ICIjOEU3N0ZGIiwgIkluY3JlYXNpbmciID0gIiNGRjYwNDAiKSkgKyAgIyBUZXh0IGNvbG91cg0KICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNCksDQogICAgICAgICAgYXhpcy50ZXh0LnkgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwLCANCiAgICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCBoanVzdCA9IDAuNSksDQogICAgICAgICAgYXhpcy50ZXh0LnggPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICBjb29yZF9mbGlwKCkgKyANCiAgICB5bGltKC0zLCAzKQ0KDQpnZ3NhdmUoZmlsZSA9ICJmaWcvbG5DVlJfY29uc3RhbnRfaW5jcmVhc2luZy5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA3LCBkcGkgPSA1MDApDQpgYGANCg0KIyMjICoqTGVhdmUtb25lLW91dCBhbmFseXNpcyoqIA0KDQojIyMjICpNb2RlbCBzcGVjaWZpY2F0aW9uKg0KYGBge3IsIGV2YWwgPSBGfQ0KIyBHZXQgYSBsaXN0IG9mIHN0dWR5IElEcyBmb3IgdGhlIExPTw0Kc3R1ZHlfaWRzIDwtIHVuaXF1ZShkYXRhJHJlZikNCm51bV9zdHVkaWVzIDwtIGxlbmd0aChzdHVkeV9pZHMpDQoNCiMgSW5pdGlhbGl6ZSBhIGxpc3QgdG8gc3RvcmUgdGhlIHJlc3VsdHMNCmxvb19yZXN1bHRzIDwtIHZlY3RvcigibGlzdCIsIG51bV9zdHVkaWVzKQ0KbmFtZXMobG9vX3Jlc3VsdHMpIDwtIHN0dWR5X2lkcw0KDQojIFNldCB1cCBwYXJhbGxlbCBwcm9jZXNzaW5nICgxNiBtb2RlbHMgYXQgYSB0aW1lKQ0KcGxhbihtdWx0aXNlc3Npb24sIHdvcmtlcnMgPSAxNikgIA0KDQojIE1vZGVsIHNwZWNpZmljYXRpb24NCmZvcm11bGEgPC0gYmYobG5DVlIgfiB0cmFpdF90eXBlIC0xICsgIyBTZXBhcmF0ZSBlZmZlY3RzIGJ5IHRyYWl0IHR5cGUNCiAgICAgICAgICAgICAgICAodHJhaXRfdHlwZS0xfHJlZikgKyAjIENvcnJlbGF0aW9uIGJldHdlZW4gdHJhaXRzIGFtb25nIHN0dWRpZXMNCiAgICAgICAgICAgICAgICAoMXxzcGVjaWVzKSArICMgU3BlY2llcy1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8Z3IocGh5bG9nZW55LCBjb3YgPSBwaHlsb19tYXRyaXgpKSArICMgUGh5bG9nZW5ldGljIHJlbGF0ZWRuZXNzDQogICAgICAgICAgICAgICAgKDF8ZXhwZXJpbWVudF9JRCkgKyAjIEV4cGVyaW1lbnQtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfG9icykgKyAjIE9ic2VydmF0aW9uLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICBmY29yKFZDVl9sbkNWUikpICMgVmFyaWFuY2UgY292YXJpYW5jZSBtYXRpeCBvZiBjb3JyZWxhdGVkIHNhbXBsaW5nIHZhcmlhbmNlcw0KDQojIERlZmluZSBwcmlvcnMNCnByaW9yID0gYygNCiAgcHJpb3IoY29uc3RhbnQoMSksIGNsYXNzID0gInNpZ21hIikNCikgIyBCZWNhdXNlIHRoZSByZXNpZHVhbCB2YXJpYW5jZS1jb3ZhcmlhbmNlIHN0cnVjdHVyZSBpcyBzcGVjaWZpZWQgaW4gZmNvciwgdGhlcmUgaXMgbm8gbmVlZCB0byBlc3RpbWF0ZSBzaWdtYSBzbyBpdCBpcyBsZWZ0IGFzIGEgY29uc3RhbnQNCg0KDQojIEZ1bmN0aW9uIHRvIGZpdCB0aGUgbW9kZWwgYWZ0ZXIgaXRlcmF0aXZlbHkgcmVtb3Zpbmcgb25lIHN0dWR5DQpsZWF2ZV9vbmVfb3V0IDwtIGZ1bmN0aW9uKHN0dWR5X2lkKSB7DQogICMgU3Vic2V0IHRoZSBkYXRhDQogIGRhdGFfc3Vic2V0IDwtIHN1YnNldChkYXRhLCByZWYgIT0gc3R1ZHlfaWQpDQogIA0KICAjIFJlY2FsY3VsYXRlIFZDViBtYXRyaXgNCiAgVkNWX2xuQ1ZSX3N1YnNldCA8LSB2Y2FsYygNCiAgICB2aSA9IHZhcl9sbkNWUiwNCiAgICBjbHVzdGVyID0gc2hhcmVkX2NvbnRyb2xfSUQsIA0KICAgIHJobyA9IDAuNSwNCiAgICBvYnMgPSBvYnMsDQogICAgZGF0YSA9IGRhdGFfc3Vic2V0DQogICkNCiAgDQogICMgRml0IHRoZSBtb2RlbA0KICBtb2RlbF9zdWJzZXQgPC0gYnJtKA0KICAgIGZvcm11bGEsIA0KICAgIGZhbWlseSA9IGdhdXNzaWFuKCksDQogICAgZGF0YSA9IGRhdGFfc3Vic2V0LCANCiAgICBkYXRhMiA9IGxpc3QoDQogICAgICBwaHlsb19tYXRyaXggPSBwaHlsb19tYXRyaXgsDQogICAgICBWQ1ZfbG5DVlIgPSBWQ1ZfbG5DVlJfc3Vic2V0DQogICAgKSwNCiAgICBwcmlvciA9IHByaW9yLA0KICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OSwgbWF4X3RyZWVkZXB0aCA9IDE1KSwNCiAgICBpdGVyID0gMjAwMCwgIyBSZWR1Y2UgdG8gMjAwMCBpdGVyYXRpb25zIHRvIHJlZHVjZSBjb21wdXRhdGlvbmFsIGRlbWFuZHMNCiAgICB3YXJtdXAgPSAxMDAwLCANCiAgICBjaGFpbnMgPSAyLCAjIE9ubHkgdHdvIGNoYWlucyB0byByZWR1Y2UgY29tcHV0YXRpb25hbCBkZW1hbmRzDQogICAgY29yZXMgPSAxLCAgICMgU2V0IGNvcmVzIHRvIDEgaW5zaWRlIHRoZSBmdW5jdGlvbg0KICAgIHNlZWQgPSAxMjMNCiAgKQ0KDQogICMgRXh0cmFjdCB0aGUgZml4ZWQgZWZmZWN0cw0KICBmaXhlZF9lZmZlY3RzIDwtIGZpeGVmKG1vZGVsX3N1YnNldCkNCiAgDQogICMgUmV0dXJuIHRoZSBmaXhlZCBlZmZlY3RzDQogIHJldHVybihsaXN0KHN0dWR5X2lkID0gc3R1ZHlfaWQsIGZpeGVkX2VmZmVjdHMgPSBmaXhlZF9lZmZlY3RzKSkNCn0NCg0KIyBSdW4gdGhlIGZ1bmN0aW9uIGluIHBhcmFsbGVsIG92ZXIgdGhlIHN0dWRpZXMNCmxvb19yZXN1bHRzIDwtIGZ1dHVyZV9sYXBwbHkoc3R1ZHlfaWRzLCBsZWF2ZV9vbmVfb3V0KQ0KDQojIFNhdmUgcmVzdWx0cw0Kc2F2ZVJEUyhsb29fcmVzdWx0cywgZmlsZSA9ICJSRGF0YS9sbkNWUl9MT09fcmVzdWx0cy5yZHMiKQ0KYGBgDQoNCiMjIyMgKk1vZGVsIHN1bW1hcnkqDQpgYGB7cn0NCiMgTG9hZCB0aGUgbGlzdCBvZiBhbGwgbW9kZWwgb3V0cHV0cw0KbG9vX2xuQ1ZSIDwtIHJlYWRSRFMoZmlsZSA9ICJSRGF0YS9sbkNWUl9MT09fcmVzdWx0cy5yZHMiKSANCg0KIyBFeHRyYWN0IGRhdGEgb24gZml4ZWQgZWZmZWN0cyBmcm9tIGVhY2ggbW9kZWwNCg0KbG9vX3Jlc3VsdHNfbG5DVlIgPC0gZG8uY2FsbChyYmluZCwgbGFwcGx5KGxvb19sbkNWUiwgZnVuY3Rpb24oeCkgew0KICAjIEV4dHJhY3Qgc3R1ZHlfaWQgYW5kIGZpeGVkX2VmZmVjdHMgZGF0YQ0KICBzdHVkeV9pZCA8LSB4JHN0dWR5X2lkDQogIGZpeGVkX2VmZmVjdHMgPC0geCRmaXhlZF9lZmZlY3RzDQogIA0KICAjIENvbnZlcnQgcm93IG5hbWVzICh0cmFpdF90eXBlKSB0byBhIGNvbHVtbiwgcmVtb3ZlIHByZWZpeCwgYW5kIGFkZCBzdHVkeV9pZA0KICBmaXhlZF9lZmZlY3RzIDwtIGRhdGEuZnJhbWUodHJhaXRfdHlwZSA9IHN1YigidHJhaXRfdHlwZSIsICIiLCByb3duYW1lcyhmaXhlZF9lZmZlY3RzKSksIGZpeGVkX2VmZmVjdHMpDQogIGZpeGVkX2VmZmVjdHMkc3R1ZHlfaWQgPC0gc3R1ZHlfaWQNCiAgDQogICMgUmVtb3ZlIHJvdyBuYW1lcw0KICByb3duYW1lcyhmaXhlZF9lZmZlY3RzKSA8LSBOVUxMDQogIA0KICByZXR1cm4oZml4ZWRfZWZmZWN0cykNCn0pKQ0KDQpsb29fcmVzdWx0c19sbkNWUiR0cmFpdF90eXBlIDwtIGZhY3Rvcihsb29fcmVzdWx0c19sbkNWUiR0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYm9keV9zaXplIiwgImZlY3VuZGl0eSIsICJzdXJ2aXZhbCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQm9keSBzaXplIiwgIkZlY3VuZGl0eSIsICJTdXJ2aXZhbCIpKQ0KDQojIFN1bW1hcmlzZSB0aGUgZGF0YQ0KbG9vX3Jlc3VsdHNfbG5DVlIgJT4lIA0KICBncm91cF9ieSh0cmFpdF90eXBlKSAlPiUgDQogIHN1bW1hcmlzZShFc3RpbWF0ZSA9IG1lYW4oRXN0aW1hdGUpLA0KICAgICAgICAgICAgU0UgPSBtZWFuKEVzdC5FcnJvciksIA0KICAgICAgICAgICAgbG93ZXJfQ0kgPSBtZWFuKFEyLjUpLA0KICAgICAgICAgICAgdXBwZXJfQ0kgPSBtZWFuKFE5Ny41KSkgIyBNZWFuIGFjcm9zcyBhbGwgbW9kZWxzDQpgYGANCg0KIyMjIyAqRGF0YSB2aXN1YWxpc2F0aW9uKiANCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD0xNX0NCiMgUGxvdA0KZ2dwbG90KCkgKw0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUsIA0KICAgICAgICAgICAgICAgbHdkPTEpICsNCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBsb29fcmVzdWx0c19sbkNWUiwgICMgUGxvdCB0aGUgY3JlZGlibGUgaW50ZXJ2YWxzIGluIHdoaXRlIGZvciBiYWNrZ3JvdW5kDQogICAgICAgICAgICAgICBhZXMoeCA9IHN0dWR5X2lkLCANCiAgICAgICAgICAgICAgICAgICB5ID0gRXN0aW1hdGUsDQogICAgICAgICAgICAgICAgICAgeW1pbiA9IFEyLjUsIA0KICAgICAgICAgICAgICAgICAgIHltYXggPSBROTcuNSwNCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IHRyYWl0X3R5cGUpLA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgIHNpemUgPSAxLA0KICAgICAgICAgICAgICAgd2lkdGggPSAwLjMpICsNCiAgICBnZW9tX3BvaW50KGRhdGEgPSBsb29fcmVzdWx0c19sbkNWUiwNCiAgICAgICAgICAgICAgIGFlcyh4ID0gc3R1ZHlfaWQsIA0KICAgICAgICAgICAgICAgICAgIHkgPSBFc3RpbWF0ZSwNCiAgICAgICAgICAgICAgICAgICBmaWxsID0gdHJhaXRfdHlwZSksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDQsIA0KICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgIGNvbG9yPSJibGFjayIpICsNCiAgICB0aGVtZV9idygpICsgICAgICMgQ3VzdG9taXplIHRoZSBwbG90DQogICAgbGFicyh5ID0gImxuQ1ZSIiwgeCA9ICIiKSArDQogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzczQjcwNiIsICIjMDZBMkJBIiwgIiNCOTA2NzQiKSkrDQogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiM3M0I3MDYiLCAiIzA2QTJCQSIsICIjQjkwNjc0IikpICsgIA0KICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNCksDQogICAgICAgICAgYXhpcy50ZXh0LnkgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDEwLCANCiAgICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCBoanVzdCA9IDAuNSksDQogICAgICAgICAgYXhpcy50ZXh0LnggPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIwKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvciA9ICJub25lIikrDQogICAgY29vcmRfZmxpcCgpKw0KICAgIHhsaW0oLTAuNCwgMC40KSsNCiAgICBmYWNldF93cmFwKH50cmFpdF90eXBlLCBuY29sID0gMykrDQogICBzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cyA9IHJldihsZXZlbHMoYXMuZmFjdG9yKGxvb19yZXN1bHRzX2xuQ1ZSJHN0dWR5X2lkKSkpKSAjIEFscGhhYmV0aWNhbCBvcmRlcg0KDQpnZ3NhdmUoZmlsZSA9ICJmaWcvbG5DVlJfTE9PLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDEyLCBkcGkgPSA1MDApDQpgYGANCg0KDQojIyMgKipVbnVzdWFsIHN0dWR5IGRlc2lnbnMqKiANCg0KIyMjIyAqTW9kZWwgc3BlY2lmaWNhdGlvbioNCmBgYHtyLCBldmFsID0gRn0NCiMgRGlzY2FyZCBvYnNlcnZhdGlvbnMgZmxhZ2dlZCBiZWNhdXNlIHRoZSBudW1iZXIgb2YgZ2VuZXJhdGlvbnMgb2Ygc2VsZWN0aW9uIHdhcyB1bmNsZWFyLCBhcyB0aGlzIHdvdWxkIG9ubHkgYWZmZWN0IHRoZSByZXN1bHRzIG9mIG1ldGEtcmVncmVzc2lvbnMNCmRhdGEgPC0gbXV0YXRlKGRhdGEsIG1pbm9yX2NvbmNlcm5zMiA9IGlmZWxzZShtaW5vcl9jb25jZXJucyA9PSAiZ2VuX3NlbGVjdGlvbiBhcHByb3hpbWF0ZSIgfCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWlub3JfY29uY2VybnMgPT0gImdlbl9zZWxlY3Rpb24gdW5kZXJlc3RpbWF0ZWQiLA0KICAgICAgICAgICAgICAgICAgICAgTkEsIG1pbm9yX2NvbmNlcm5zKSkgDQoNCiMgRmlsdGVyIHRvIGRhdGEgd2l0aG91dCBzb3VyY2VzIG9mIHByb2NlZHVyYWwgIGNvbmNlcm5zLg0KZGF0YV9jb25jZXJucyA8LSBmaWx0ZXIoZGF0YSwgaXMubmEobWFqb3JfY29uY2VybnMpPT1UICYgaXMubmEobWlub3JfY29uY2VybnMyKT09VCkNCg0KIyBEcm9wIHRpcHMgdGhhdCBhcmUgbm90IGluIHRoZSB3YXJtIGRhdGFzZXQNCnRpcHNfdG9fZHJvcCA8LSBzZXRkaWZmKHBoeWxvX3RyZWUkdGlwLmxhYmVsLCBkYXRhX2NvbmNlcm5zJHBoeWxvZ2VueSkNCnBoeWxvX3RyZWVfY29uY2VybnMgPC0gZHJvcC50aXAocGh5bG9fdHJlZSwgdGlwc190b19kcm9wKQ0KDQojIENvbXB1dGUgcGh5bG9nZW5ldGljIGNvcnJlbGF0aW9uIG1hdHJpeA0KcGh5bG9fbWF0cml4X2NvbmNlcm5zIDwtIHZjdihwaHlsb190cmVlX2NvbmNlcm5zLCBjb3IgPSBUKSAgIyBUaGUgdmN2IGZ1bmN0aW9uIHJldHVybnMgYSB2YXJpYW5jZS1jb3ZhcmlhbmNlIG1hdHJpeA0KDQojIENvbnZlcnQgdGliYmxlIHRvIGRhdGEgZnJhbWUNCmRhdGFfY29uY2VybnMgPC0gYXMuZGF0YS5mcmFtZShkYXRhX2NvbmNlcm5zKQ0KDQojIENhbGN1bGF0ZSBWQ1YgbWF0cml4DQpWQ1ZfbG5DVlJfY29uY2VybnMgPC0gdmNhbGModmkgPSB2YXJfbG5DVlIsDQogICAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXIgPSBzaGFyZWRfY29udHJvbF9JRCwgDQogICAgICAgICAgICAgICAgICAgICAgIHJobyA9IDAuNSwNCiAgICAgICAgICAgICAgICAgICAgICAgb2JzID0gb2JzLA0KICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YV9jb25jZXJucykgDQoNCiMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KZm9ybXVsYSA8LSBiZihsbkNWUiB+IDAgKyB0cmFpdF90eXBlOndhcm1fY29sZCArIHRyYWl0X3R5cGU6d2FybV9jb2xkOmFzc2F5X3RlbXBfZGlmZiArICMgU2VwYXJhdGUgZWZmZWN0cyBieSB0cmFpdCB0eXBlDQogICAgICAgICAgICAgICAgKHRyYWl0X3R5cGUtMXxyZWYpICsgIyBDb3JyZWxhdGlvbiBiZXR3ZWVuIHRyYWl0cyBhbW9uZyBzdHVkaWVzDQogICAgICAgICAgICAgICAgKDF8c3BlY2llcykgKyAjIFNwZWNpZXMtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfGdyKHBoeWxvZ2VueSwgY292ID0gcGh5bG9fbWF0cml4X2NvbmNlcm5zKSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5DVlJfY29uY2VybnMpKSAjIFZhcmlhbmNlIGNvdmFyaWFuY2UgbWF0aXggb2YgY29ycmVsYXRlZCBzYW1wbGluZyB2YXJpYW5jZXMNCg0KIyBEZWZpbmUgcHJpb3JzDQpwcmlvciA9IGMoDQogIHByaW9yKGNvbnN0YW50KDEpLCBjbGFzcyA9ICJzaWdtYSIpDQopICMgQmVjYXVzZSB0aGUgcmVzaWR1YWwgdmFyaWFuY2UtY292YXJpYW5jZSBzdHJ1Y3R1cmUgaXMgc3BlY2lmaWVkIGluIGZjb3IsIHRoZXJlIGlzIG5vIG5lZWQgdG8gZXN0aW1hdGUgc2lnbWEgc28gaXQgaXMgbGVmdCBhcyBhIGNvbnN0YW50DQoNCiMgRml0IG1vZGVsDQpsbkNWUl9tb2RlbF9jb25jZXJucyA8LSBicm0oZm9ybXVsYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IGdhdXNzaWFuKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhX2NvbmNlcm5zLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTIgPSBsaXN0KHBoeWxvX21hdHJpeF9jb25jZXJucyA9IHBoeWxvX21hdHJpeF9jb25jZXJucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZDVl9sbkNWUl9jb25jZXJucyA9IFZDVl9sbkNWUl9jb25jZXJucyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yID0gcHJpb3IsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OSwgbWF4X3RyZWVkZXB0aCA9IDE1KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDQwMDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXJtdXAgPSAyMDAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFpbnMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEyMykgDQojIFNhdmUgbW9kZWwNCnNhdmVSRFMobG5DVlJfbW9kZWxfY29uY2VybnMsIGZpbGUgPSAiUkRhdGEvbG5DVlJfbW9kZWxfY29uY2VybnMucmRzIikNCmBgYA0KDQojIyMjICpNb2RlbCBzdW1tYXJ5Kg0KYGBge3J9DQojIExvYWQgbW9kZWwNCmxuQ1ZSX21vZGVsX2NvbmNlcm5zIDwtIHJlYWRSRFMoIlJEYXRhL2xuQ1ZSX21vZGVsX2NvbmNlcm5zLnJkcyIpDQoNCiMgRGlzcGxheSBtb2RlbCBvdXRwdXQgDQpzdW1tYXJ5KGxuQ1ZSX21vZGVsX2NvbmNlcm5zKQ0KDQojIENsZWFuZWQgbW9kZWwgb3V0cHV0DQphcy5kYXRhLmZyYW1lKGZpeGVmKGxuQ1ZSX21vZGVsX2NvbmNlcm5zLCBzdW1tYXJ5ID0gVFJVRSkpICU+JQ0KICAjIFJlbmFtZSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgZm9yIGNsZWFuZXIgZGlzcGxheQ0KICByb3duYW1lc190b19jb2x1bW4odmFyID0gIlBhcmFtZXRlciIpICU+JSANCiAgbXV0YXRlKA0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKyk6d2FybV9jb2xkKGNvbGR8d2FybSkiLCAiXFwxKFxcMikiLCBQYXJhbWV0ZXIpLA0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKylcXCh3YXJtXFwpOmFzc2F5X3RlbXBfZGlmZiIsICJcXDEod2FybSk6IGFzc2F5X3RlbXBfZGlmZiIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkRhdGEgdmlzdWFsaXNhdGlvbiogDQpgYGB7ciwgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQ9MTB9DQojIERpc2NhcmQgb2JzZXJ2YXRpb25zIGZsYWdnZWQgYmVjYXVzZSB0aGUgbnVtYmVyIG9mIGdlbmVyYXRpb25zIG9mIHNlbGVjdGlvbiB3YXMgdW5jbGVhciwgYXMgdGhpcyB3b3VsZCBvbmx5IGFmZmVjdCB0aGUgcmVzdWx0cyBvZiBtZXRhLXJlZ3Jlc3Npb25zDQpkYXRhIDwtIG11dGF0ZShkYXRhLCBtaW5vcl9jb25jZXJuczIgPSBpZmVsc2UobWlub3JfY29uY2VybnMgPT0gImdlbl9zZWxlY3Rpb24gYXBwcm94aW1hdGUiIHwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbm9yX2NvbmNlcm5zID09ICJnZW5fc2VsZWN0aW9uIHVuZGVyZXN0aW1hdGVkIiwNCiAgICAgICAgICAgICAgICAgICAgIE5BLCBtaW5vcl9jb25jZXJucykpIA0KDQojIEZpbHRlciB0byBkYXRhIHdpdGhvdXQgc291cmNlcyBvZiBwcm9jZWR1cmFsICBjb25jZXJucy4NCmRhdGFfY29uY2VybnMgPC0gZmlsdGVyKGRhdGEsIGlzLm5hKG1ham9yX2NvbmNlcm5zKT09VCAmIGlzLm5hKG1pbm9yX2NvbmNlcm5zMik9PVQpDQoNCiMgQ2FsY3VsYXRlIHNhbXBsZSBzaXplcyBhbmQgc3R1ZHkgY291bnRzDQpzYW1wbGVfc2l6ZXNfY29uY2VybnMgPC0gZGF0YV9jb25jZXJucyAlPiUNCiAgZ3JvdXBfYnkodHJhaXRfdHlwZSwgd2FybV9jb2xkKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGVzdGltYXRlcyA9IG4oKSwNCiAgICBzdHVkaWVzID0gbl9kaXN0aW5jdChyZWYpDQogICkNCg0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucw0KZW1tZWFuc19jb25jZXJucyA8LSBhcy5kYXRhLmZyYW1lKGVtbWVhbnMoDQogIGxuQ1ZSX21vZGVsX2NvbmNlcm5zLA0KICBzcGVjcyA9IH4gYXNzYXlfdGVtcF9kaWZmIHwgdHJhaXRfdHlwZSAqIHdhcm1fY29sZCwNCiAgYXQgPSBsaXN0KGFzc2F5X3RlbXBfZGlmZiA9IHNlcShtaW4oZGF0YV9jb25jZXJucyRhc3NheV90ZW1wX2RpZmYpLCBtYXgoZGF0YV9jb25jZXJucyRhc3NheV90ZW1wX2RpZmYpLCBieSA9IDAuNSkpKSkNCg0KIyBDYWxjdWxhdGUgcmFuZ2Ugb2YgdmFsdWVzIGZvciBlYWNoIGNhdGVnb3J5DQpyYW5nZV9kZl9jb25jZXJucyA8LSBkYXRhX2NvbmNlcm5zICU+JQ0KICBncm91cF9ieSh0cmFpdF90eXBlLCB3YXJtX2NvbGQpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWluX2Fzc2F5X3RlbXBfZGlmZiA9IG1pbihhc3NheV90ZW1wX2RpZmYpLA0KICAgIG1heF9hc3NheV90ZW1wX2RpZmYgPSBtYXgoYXNzYXlfdGVtcF9kaWZmKQ0KICApDQoNCmVtbWVhbnNfY29uY2VybnMkdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19jb25jZXJucyR0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYm9keV9zaXplIiwgImZlY3VuZGl0eSIsICJzdXJ2aXZhbCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQm9keSBzaXplIiwgIkZlY3VuZGl0eSIsICJTdXJ2aXZhbCIpKQ0KDQplbW1lYW5zX2NvbmNlcm5zJHdhcm1fY29sZCA8LSBmYWN0b3IoZW1tZWFuc19jb25jZXJucyR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KDQojIFRhaWxvciBwcmVkaWN0aW9ucyB0byB0aGUgcmFuZ2Ugb2YgdGhlIGRhdGENCmVtbWVhbnNfY29uY2VybnMgPC0gZW1tZWFuc19jb25jZXJucyAlPiUNCiAgbGVmdF9qb2luKHJhbmdlX2RmX2NvbmNlcm5zLCBieSA9IGMoInRyYWl0X3R5cGUiLCAid2FybV9jb2xkIikpICU+JQ0KICBmaWx0ZXIoDQogICAgYXNzYXlfdGVtcF9kaWZmID49IG1pbl9hc3NheV90ZW1wX2RpZmYsDQogICAgYXNzYXlfdGVtcF9kaWZmIDw9IG1heF9hc3NheV90ZW1wX2RpZmYNCiAgKQ0KDQojIFBsb3QNCmdncGxvdCgpICsgDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgIyBIb3Jpem9udGFsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSkgKyAgDQogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgIyBWZXJ0aWNhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUpICsgDQogICAgZ2VvbV9wb2ludChkYXRhID0gZGF0YV9jb25jZXJucywgIyBFZmZlY3Qgc2l6ZXMsIHNjYWxlZCBieSBwcmVjaXNpb24NCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gYXNzYXlfdGVtcF9kaWZmLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5DVlIsIA0KICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxL3NxcnQodmFyX2xuQ1ZSKSwgDQogICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwgDQogICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNywgDQogICAgICAgICAgICAgICAgICBzdHJva2UgPSAxLA0KICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjA1KSkgKyANCiAgICAgZ2VvbV9yaWJib24oZGF0YSA9IGVtbWVhbnNfY29uY2VybnMsICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IGFzc2F5X3RlbXBfZGlmZiwNCiAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICBmaWxsID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgYWxwaGEgPSAuNSkgKyANCiAgICAgZ2VvbV9saW5lKGRhdGEgPSBlbW1lYW5zX2NvbmNlcm5zLCAgIyBQcmVkaWN0ZWQgcmVncmVzc2lvbiBsaW5lDQogICAgICAgICAgICAgICBhZXMoeSA9IGVtbWVhbiwNCiAgICAgICAgICAgICAgICAgICB4ID0gYXNzYXlfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArIA0KICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzX2NvbmNlcm5zLCANCiAgICAgICAgICAgICAgYWVzKHggPSBJbmYsIA0KICAgICAgICAgICAgICAgICAgeSA9IGlmZWxzZSh3YXJtX2NvbGQgPT0gIldhcm0iLCAtMiwgLTIuNzUpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICANCiAgZmFjZXRfd3JhcCh+IHRyYWl0X3R5cGUsIG5jb2wgPSAxKSArICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJBc3NheSB0ZW1wZXJhdHVyZSBkaWZmZXJlbmNlIiwgeSA9ICJsbkNWUiIsDQogICAgICAgY29sID0gIlJlZ2ltZSIpICsNCiAgdGhlbWVfYncoKSArIA0KICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDIsIDgpKSsgDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDI1LCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTgpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgICAgYXhpcy50ZXh0LnkgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwLCANCiAgICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCBoanVzdCA9IDAuNSksDQogICAgICAgICAgYXhpcy50ZXh0LnggPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuNSksDQogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMjIpKSArDQogICAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIHNpemUgPSAibm9uZSIpKw0KICAgIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygtMywgMykpDQoNCmdnc2F2ZShmaWxlID0gImZpZy9sbkNWUl9jb25jZXJucy5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA3LCBkcGkgPSA1MDApDQpgYGANCg0KIyMgKipDaGFuZ2VzIGluIHRyYWl0IHZhcmlhbmNlIChsblZSKSoqIHsudGFic2V0IC50YWJzZXRfZmFkZSAudGFic2V0X3BpbGxzfQ0KDQojIyMgKipDb25zdGFudCB2cy4gaW5jcmVhc2luZyB0ZW1wZXJhdHVyZXMqKiANCg0KIyMjIyAqTW9kZWwgc3BlY2lmaWNhdGlvbioNCmBgYHtyLCBldmFsID0gRn0NCiMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KZm9ybXVsYSA8LSBiZihsblZSIH4gMCArIHRyYWl0X3R5cGU6Y29uc3RhbnRfaW5jcmVhc2luZyArIHRyYWl0X3R5cGU6Y29uc3RhbnRfaW5jcmVhc2luZzphc3NheV90ZW1wX2RpZmYgKyAjIFNlcGFyYXRlIGVmZmVjdHMgYnkgdHJhaXQgdHlwZQ0KICAgICAgICAgICAgICAgICh0cmFpdF90eXBlLTF8cmVmKSArICMgQ29ycmVsYXRpb24gYmV0d2VlbiB0cmFpdHMgYW1vbmcgc3R1ZGllcw0KICAgICAgICAgICAgICAgICgxfHNwZWNpZXMpICsgIyBTcGVjaWVzLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxncihwaHlsb2dlbnksIGNvdiA9IHBoeWxvX21hdHJpeF93YXJtKSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5WUl93YXJtKSkgIyBWYXJpYW5jZSBjb3ZhcmlhbmNlIG1hdGl4IG9mIGNvcnJlbGF0ZWQgc2FtcGxpbmcgdmFyaWFuY2VzDQoNCiMgRGVmaW5lIHByaW9ycw0KcHJpb3IgPSBjKA0KICBwcmlvcihjb25zdGFudCgxKSwgY2xhc3MgPSAic2lnbWEiKQ0KKSAjIEJlY2F1c2UgdGhlIHJlc2lkdWFsIHZhcmlhbmNlLWNvdmFyaWFuY2Ugc3RydWN0dXJlIGlzIHNwZWNpZmllZCBpbiBmY29yLCB0aGVyZSBpcyBubyBuZWVkIHRvIGVzdGltYXRlIHNpZ21hIHNvIGl0IGlzIGxlZnQgYXMgYSBjb25zdGFudA0KDQojIEZpdCBtb2RlbA0KbG5WUl9tb2RlbF9jb25zdGFudF9pbmNyZWFzaW5nIDwtIGJybShmb3JtdWxhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IGdhdXNzaWFuKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YV93YXJtLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEyID0gbGlzdChwaHlsb19tYXRyaXhfd2FybSA9IHBoeWxvX21hdHJpeF93YXJtLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZDVl9sblZSX3dhcm0gPSBWQ1ZfbG5WUl93YXJtKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yID0gcHJpb3IsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTksIG1heF90cmVlZGVwdGggPSAxNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyID0gNDAwMCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXJtdXAgPSAyMDAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhaW5zID0gNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JlcyA9IDQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEyMykgDQoNCiMgU2F2ZSBtb2RlbA0Kc2F2ZVJEUyhsblZSX21vZGVsX2NvbnN0YW50X2luY3JlYXNpbmcsIGZpbGUgPSAiUkRhdGEvbG5WUl9tb2RlbF9jb25zdGFudF9pbmNyZWFzaW5nLnJkcyIpDQpgYGANCg0KIyMjIyAqTW9kZWwgb3V0cHV0Kg0KYGBge3J9DQojIExvYWQgbW9kZWwNCmxuVlJfbW9kZWxfY29uc3RhbnRfaW5jcmVhc2luZyA8LSByZWFkUkRTKCJSRGF0YS9sblZSX21vZGVsX2NvbnN0YW50X2luY3JlYXNpbmcucmRzIikNCg0KIyBEaXNwbGF5IG1vZGVsIG91dHB1dCANCnN1bW1hcnkobG5WUl9tb2RlbF9jb25zdGFudF9pbmNyZWFzaW5nKQ0KDQojIENsZWFuZWQgbW9kZWwgb3V0cHV0DQphcy5kYXRhLmZyYW1lKGZpeGVmKGxuVlJfbW9kZWxfY29uc3RhbnRfaW5jcmVhc2luZywgc3VtbWFyeSA9IFRSVUUpKSAlPiUNCiAgIyBSZW5hbWUgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGZvciBjbGVhbmVyIGRpc3BsYXkNCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJQYXJhbWV0ZXIiKSAlPiUNCiAgbXV0YXRlKA0KICAgICMgU2ltcGxpZnkgYHRyYWl0X3R5cGVgIGFuZCBgY29uc3RhbnRfaW5jcmVhc2luZ2AgaW50ZXJhY3Rpb25zDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKTpjb25zdGFudF9pbmNyZWFzaW5nKGNvbnN0YW50fGluY3JlYXNpbmcpIiwgIlxcMShcXDIpIiwgUGFyYW1ldGVyKSwNCiAgICAjIEFkanVzdCBmb3IgYXNzYXlfdGVtcF9kaWZmDQogICAgUGFyYW1ldGVyID0gZ3N1YigidHJhaXRfdHlwZShbYS16X10rKVxcKChjb25zdGFudHxpbmNyZWFzaW5nKVxcKTphc3NheV90ZW1wX2RpZmYiLCAiXFwxKFxcMik6IGFzc2F5X3RlbXBfZGlmZiIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkNvbnRyYXN0cyogDQpgYGB7cn0NCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbXMgPC0gZW1tZWFucyhsblZSX21vZGVsX2NvbnN0YW50X2luY3JlYXNpbmcsIA0KICAgICAgICAgICAgICAgIHNwZWNzID0gfiBjb25zdGFudF9pbmNyZWFzaW5nIHwgdHJhaXRfdHlwZSwNCiAgICAgICAgICAgICAgICBhdCA9IGxpc3QoYXNzYXlfdGVtcF9kaWZmID0gMCkpDQoNCiMgR2VuZXJhdGUgY29udHJhc3RzDQpjb250cmFzdChlbW1zLCBtZXRob2QgPSAicGFpcndpc2UiKQ0KYGBgDQoNCiMjIyMgKkRhdGEgdmlzdWFsaXNhdGlvbioNCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD0xMH0NCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbWVhbnNfY29uc3RhbnRfaW5jcmVhc2luZyA8LSBhcy5kYXRhLmZyYW1lKGVtbWVhbnMobG5WUl9tb2RlbF9jb25zdGFudF9pbmNyZWFzaW5nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlY3MgPSB+IGNvbnN0YW50X2luY3JlYXNpbmcgfCB0cmFpdF90eXBlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdCA9IGxpc3QoYXNzYXlfdGVtcF9kaWZmID0gMCkpKQ0KDQplbW1lYW5zX2NvbnN0YW50X2luY3JlYXNpbmckdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19jb25zdGFudF9pbmNyZWFzaW5nJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfY29uc3RhbnRfaW5jcmVhc2luZyRjb25zdGFudF9pbmNyZWFzaW5nIDwtIGZhY3RvcihlbW1lYW5zX2NvbnN0YW50X2luY3JlYXNpbmckY29uc3RhbnRfaW5jcmVhc2luZywgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbnN0YW50IiwgImluY3JlYXNpbmciKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbnN0YW50IiwgIkluY3JlYXNpbmciKSkNCg0KIyBQbG90DQpnZ3Bsb3QoKSArDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgIyBIb3Jpem9udGFsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSwgDQogICAgICAgICAgICAgICBsd2Q9MSkgKw0KICAgIGdlb21fcXVhc2lyYW5kb20oZGF0YSA9IGRhdGFfd2FybSwgICAgICMgUGxvdCBlZmZlY3Qgc2l6ZXMsIHNjYWxlZCBieSBwcmVjaXNpb24NCiAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTpjb25zdGFudF9pbmNyZWFzaW5nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5WUiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHRyYWl0X3R5cGU6Y29uc3RhbnRfaW5jcmVhc2luZywgDQogICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5WUikpLCANCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsDQogICAgICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMjUsIA0KICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjQ1KSArDQogICAgZ2VvbV9lcnJvcmJhcihkYXRhID0gZW1tZWFuc19jb25zdGFudF9pbmNyZWFzaW5nLCAgIyBQbG90IHRoZSBwb2ludCBlc3RpbWF0ZXMgaW4gd2hpdGUgZm9yIGJhY2tncm91bmQNCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gdHJhaXRfdHlwZTpjb25zdGFudF9pbmNyZWFzaW5nLCANCiAgICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBEKSwgDQogICAgICAgICAgICAgICAgICBjb2xvcj0id2hpdGUiLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDIuNSwNCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4xNykgKw0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGVtbWVhbnNfY29uc3RhbnRfaW5jcmVhc2luZywgICMgUGxvdCB0aGUgY3JlZGlibGUgaW50ZXJ2YWxzIGluIHdoaXRlIGZvciBiYWNrZ3JvdW5kDQogICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6Y29uc3RhbnRfaW5jcmVhc2luZywgDQogICAgICAgICAgICAgICAgICAgeSA9IGVtbWVhbiksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDQsIA0KICAgICAgICAgICAgICAgc3Ryb2tlID0gMiwNCiAgICAgICAgICAgICAgIGNvbG9yPSJ3aGl0ZSIsDQogICAgICAgICAgICAgICBmaWxsID0gIndoaXRlIikgKw0KICAgIGdlb21fZXJyb3JiYXIoZGF0YSA9IGVtbWVhbnNfY29uc3RhbnRfaW5jcmVhc2luZywgIyBQbG90IHRoZSBwb2ludCBlc3RpbWF0ZXMgDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6Y29uc3RhbnRfaW5jcmVhc2luZywgDQogICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCksIA0KICAgICAgICAgICAgICAgICAgY29sb3I9ImJsYWNrIiwNCiAgICAgICAgICAgICAgICAgIHNpemUgPSAyLA0KICAgICAgICAgICAgICAgICAgd2lkdGggPSAwLjE1KSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gZW1tZWFuc19jb25zdGFudF9pbmNyZWFzaW5nLCAjIFBsb3QgdGhlIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgYWVzKHggPSB0cmFpdF90eXBlOmNvbnN0YW50X2luY3JlYXNpbmcsIA0KICAgICAgICAgICAgICAgICAgIHkgPSBlbW1lYW4pLA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgIHNpemUgPSAzLjUsIA0KICAgICAgICAgICAgICAgc3Ryb2tlID0gMiwNCiAgICAgICAgICAgICAgIGNvbG9yPSJibGFjayIsDQogICAgICAgICAgICAgICBmaWxsID0gIndoaXRlIikgKw0KICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzX3dhcm0sICAjIFNhbXBsZSBzaXplIGFubm90YXRpb25zIA0KICAgICAgICAgICAgICBhZXMoeCA9IHRyYWl0X3R5cGU6Y29uc3RhbnRfaW5jcmVhc2luZywgDQogICAgICAgICAgICAgICAgICB5ID0gMy41LA0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IGNvbnN0YW50X2luY3JlYXNpbmcpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICAgIHRoZW1lX2J3KCkgKyAgICAgIyBDdXN0b21pemUgdGhlIHBsb3QNCiAgICBsYWJzKHkgPSAibG5WUiIsIHggPSAiIikgKw0KICAgIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgOCkpKyANCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjOEU3N0ZGIiwgIiNGRjYwNDAiLCAiIzhFNzdGRiIsICIjRkY2MDQwIiwgIiM4RTc3RkYiLCAiI0ZGNjA0MCIpKSsNCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiQ29uc3RhbnQiID0gIiM4RTc3RkYiLCAiSW5jcmVhc2luZyIgPSAiI0ZGNjA0MCIpKSArICAjIFRleHQgY29sb3VyDQogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpKSArDQogICAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIHNpemUgPSAibm9uZSIpKw0KICAgIGNvb3JkX2ZsaXAoKSArIA0KICAgIHlsaW0oLTMuNSwgMy41KQ0KDQpnZ3NhdmUoZmlsZSA9ICJmaWcvbG5WUl9jb25zdGFudF9pbmNyZWFzaW5nLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIGRwaSA9IDUwMCkNCmBgYA0KDQojIyMgKipMZWF2ZS1vbmUtb3V0IGFuYWx5c2lzKiogDQoNCiMjIyMgKk1vZGVsIHNwZWNpZmljYXRpb24qDQpgYGB7ciwgZXZhbCA9IEZ9DQojIEdldCBhIGxpc3Qgb2Ygc3R1ZHkgSURzIGZvciB0aGUgTE9PDQpzdHVkeV9pZHMgPC0gdW5pcXVlKGRhdGEkcmVmKQ0KbnVtX3N0dWRpZXMgPC0gbGVuZ3RoKHN0dWR5X2lkcykNCg0KIyBJbml0aWFsaXplIGEgbGlzdCB0byBzdG9yZSB0aGUgcmVzdWx0cw0KbG9vX3Jlc3VsdHMgPC0gdmVjdG9yKCJsaXN0IiwgbnVtX3N0dWRpZXMpDQpuYW1lcyhsb29fcmVzdWx0cykgPC0gc3R1ZHlfaWRzDQoNCiMgU2V0IHVwIHBhcmFsbGVsIHByb2Nlc3NpbmcgKDE2IG1vZGVscyBhdCBhIHRpbWUpDQpwbGFuKG11bHRpc2Vzc2lvbiwgd29ya2VycyA9IDE2KSAgDQoNCiMgTW9kZWwgc3BlY2lmaWNhdGlvbg0KZm9ybXVsYSA8LSBiZihsblZSIH4gdHJhaXRfdHlwZSAtMSArICMgU2VwYXJhdGUgZWZmZWN0cyBieSB0cmFpdCB0eXBlDQogICAgICAgICAgICAgICAgKHRyYWl0X3R5cGUtMXxyZWYpICsgIyBDb3JyZWxhdGlvbiBiZXR3ZWVuIHRyYWl0cyBhbW9uZyBzdHVkaWVzDQogICAgICAgICAgICAgICAgKDF8c3BlY2llcykgKyAjIFNwZWNpZXMtbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgICgxfGdyKHBoeWxvZ2VueSwgY292ID0gcGh5bG9fbWF0cml4KSkgKyAjIFBoeWxvZ2VuZXRpYyByZWxhdGVkbmVzcw0KICAgICAgICAgICAgICAgICgxfGV4cGVyaW1lbnRfSUQpICsgIyBFeHBlcmltZW50LWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxvYnMpICsgIyBPYnNlcnZhdGlvbi1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgZmNvcihWQ1ZfbG5WUikpICMgVmFyaWFuY2UgY292YXJpYW5jZSBtYXRpeCBvZiBjb3JyZWxhdGVkIHNhbXBsaW5nIHZhcmlhbmNlcw0KDQojIERlZmluZSBwcmlvcnMNCnByaW9yID0gYygNCiAgcHJpb3IoY29uc3RhbnQoMSksIGNsYXNzID0gInNpZ21hIikNCikgIyBCZWNhdXNlIHRoZSByZXNpZHVhbCB2YXJpYW5jZS1jb3ZhcmlhbmNlIHN0cnVjdHVyZSBpcyBzcGVjaWZpZWQgaW4gZmNvciwgdGhlcmUgaXMgbm8gbmVlZCB0byBlc3RpbWF0ZSBzaWdtYSBzbyBpdCBpcyBsZWZ0IGFzIGEgY29uc3RhbnQNCg0KDQojIEZ1bmN0aW9uIHRvIGZpdCB0aGUgbW9kZWwgYWZ0ZXIgaXRlcmF0aXZlbHkgcmVtb3Zpbmcgb25lIHN0dWR5DQpsZWF2ZV9vbmVfb3V0IDwtIGZ1bmN0aW9uKHN0dWR5X2lkKSB7DQogICMgU3Vic2V0IHRoZSBkYXRhDQogIGRhdGFfc3Vic2V0IDwtIHN1YnNldChkYXRhLCByZWYgIT0gc3R1ZHlfaWQpDQogIA0KICAjIFJlY2FsY3VsYXRlIFZDViBtYXRyaXgNCiAgVkNWX2xuVlJfc3Vic2V0IDwtIHZjYWxjKA0KICAgIHZpID0gdmFyX2xuVlIsDQogICAgY2x1c3RlciA9IHNoYXJlZF9jb250cm9sX0lELCANCiAgICByaG8gPSAwLjUsDQogICAgb2JzID0gb2JzLA0KICAgIGRhdGEgPSBkYXRhX3N1YnNldA0KICApDQogIA0KICAjIEZpdCB0aGUgbW9kZWwNCiAgbW9kZWxfc3Vic2V0IDwtIGJybSgNCiAgICBmb3JtdWxhLCANCiAgICBmYW1pbHkgPSBnYXVzc2lhbigpLA0KICAgIGRhdGEgPSBkYXRhX3N1YnNldCwgDQogICAgZGF0YTIgPSBsaXN0KA0KICAgICAgcGh5bG9fbWF0cml4ID0gcGh5bG9fbWF0cml4LA0KICAgICAgVkNWX2xuVlIgPSBWQ1ZfbG5WUl9zdWJzZXQNCiAgICApLA0KICAgIHByaW9yID0gcHJpb3IsDQogICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk5LCBtYXhfdHJlZWRlcHRoID0gMTUpLA0KICAgIGl0ZXIgPSAyMDAwLCAjIFJlZHVjZSB0byAyMDAwIGl0ZXJhdGlvbnMgdG8gcmVkdWNlIGNvbXB1dGF0aW9uYWwgZGVtYW5kcw0KICAgIHdhcm11cCA9IDEwMDAsIA0KICAgIGNoYWlucyA9IDIsICMgT25seSB0d28gY2hhaW5zIHRvIHJlZHVjZSBjb21wdXRhdGlvbmFsIGRlbWFuZHMNCiAgICBjb3JlcyA9IDEsICAgIyBTZXQgY29yZXMgdG8gMSBpbnNpZGUgdGhlIGZ1bmN0aW9uDQogICAgc2VlZCA9IDEyMw0KICApDQoNCiAgIyBFeHRyYWN0IHRoZSBmaXhlZCBlZmZlY3RzDQogIGZpeGVkX2VmZmVjdHMgPC0gZml4ZWYobW9kZWxfc3Vic2V0KQ0KICANCiAgIyBSZXR1cm4gdGhlIGZpeGVkIGVmZmVjdHMNCiAgcmV0dXJuKGxpc3Qoc3R1ZHlfaWQgPSBzdHVkeV9pZCwgZml4ZWRfZWZmZWN0cyA9IGZpeGVkX2VmZmVjdHMpKQ0KfQ0KDQojIFJ1biB0aGUgZnVuY3Rpb24gaW4gcGFyYWxsZWwgb3ZlciB0aGUgc3R1ZGllcw0KbG9vX3Jlc3VsdHMgPC0gZnV0dXJlX2xhcHBseShzdHVkeV9pZHMsIGxlYXZlX29uZV9vdXQpDQoNCiMgU2F2ZSByZXN1bHRzDQpzYXZlUkRTKGxvb19yZXN1bHRzLCBmaWxlID0gIlJEYXRhL2xuVlJfTE9PX3Jlc3VsdHMucmRzIikNCmBgYA0KDQojIyMjICpNb2RlbCBzdW1tYXJ5Kg0KYGBge3J9DQojIExvYWQgdGhlIGxpc3Qgb2YgYWxsIG1vZGVsIG91dHB1dHMNCmxvb19sblZSIDwtIHJlYWRSRFMoZmlsZSA9ICJSRGF0YS9sblZSX0xPT19yZXN1bHRzLnJkcyIpIA0KDQojIEV4dHJhY3QgZGF0YSBvbiBmaXhlZCBlZmZlY3RzIGZyb20gZWFjaCBtb2RlbA0KDQpsb29fcmVzdWx0c19sblZSIDwtIGRvLmNhbGwocmJpbmQsIGxhcHBseShsb29fbG5WUiwgZnVuY3Rpb24oeCkgew0KICAjIEV4dHJhY3Qgc3R1ZHlfaWQgYW5kIGZpeGVkX2VmZmVjdHMgZGF0YQ0KICBzdHVkeV9pZCA8LSB4JHN0dWR5X2lkDQogIGZpeGVkX2VmZmVjdHMgPC0geCRmaXhlZF9lZmZlY3RzDQogIA0KICAjIENvbnZlcnQgcm93IG5hbWVzICh0cmFpdF90eXBlKSB0byBhIGNvbHVtbiwgcmVtb3ZlIHByZWZpeCwgYW5kIGFkZCBzdHVkeV9pZA0KICBmaXhlZF9lZmZlY3RzIDwtIGRhdGEuZnJhbWUodHJhaXRfdHlwZSA9IHN1YigidHJhaXRfdHlwZSIsICIiLCByb3duYW1lcyhmaXhlZF9lZmZlY3RzKSksIGZpeGVkX2VmZmVjdHMpDQogIGZpeGVkX2VmZmVjdHMkc3R1ZHlfaWQgPC0gc3R1ZHlfaWQNCiAgDQogICMgUmVtb3ZlIHJvdyBuYW1lcw0KICByb3duYW1lcyhmaXhlZF9lZmZlY3RzKSA8LSBOVUxMDQogIA0KICByZXR1cm4oZml4ZWRfZWZmZWN0cykNCn0pKQ0KDQpsb29fcmVzdWx0c19sblZSJHRyYWl0X3R5cGUgPC0gZmFjdG9yKGxvb19yZXN1bHRzX2xuVlIkdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KIyBTdW1tYXJpc2UgdGhlIGRhdGENCmxvb19yZXN1bHRzX2xuVlIgJT4lIA0KICBncm91cF9ieSh0cmFpdF90eXBlKSAlPiUgDQogIHN1bW1hcmlzZShFc3RpbWF0ZSA9IG1lYW4oRXN0aW1hdGUpLA0KICAgICAgICAgICAgU0UgPSBtZWFuKEVzdC5FcnJvciksIA0KICAgICAgICAgICAgbG93ZXJfQ0kgPSBtZWFuKFEyLjUpLA0KICAgICAgICAgICAgdXBwZXJfQ0kgPSBtZWFuKFE5Ny41KSkgIyBNZWFuIGFjcm9zcyBhbGwgbW9kZWxzDQpgYGANCg0KIyMjIyAqRGF0YSB2aXN1YWxpc2F0aW9uKiANCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD0xNX0NCiMgUGxvdA0KZ2dwbG90KCkgKw0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUsIA0KICAgICAgICAgICAgICAgbHdkPTEpICsNCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBsb29fcmVzdWx0c19sblZSLCAgIyBQbG90IHRoZSBjcmVkaWJsZSBpbnRlcnZhbHMgaW4gd2hpdGUgZm9yIGJhY2tncm91bmQNCiAgICAgICAgICAgICAgIGFlcyh4ID0gc3R1ZHlfaWQsIA0KICAgICAgICAgICAgICAgICAgIHkgPSBFc3RpbWF0ZSwNCiAgICAgICAgICAgICAgICAgICB5bWluID0gUTIuNSwgDQogICAgICAgICAgICAgICAgICAgeW1heCA9IFE5Ny41LA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gdHJhaXRfdHlwZSksDQogICAgICAgICAgICAgICBzaGFwZSA9IDIxLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDEsDQogICAgICAgICAgICAgICB3aWR0aCA9IDAuMykgKw0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGxvb19yZXN1bHRzX2xuVlIsDQogICAgICAgICAgICAgICBhZXMoeCA9IHN0dWR5X2lkLCANCiAgICAgICAgICAgICAgICAgICB5ID0gRXN0aW1hdGUsDQogICAgICAgICAgICAgICAgICAgZmlsbCA9IHRyYWl0X3R5cGUpLA0KICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwNCiAgICAgICAgICAgICAgIHNpemUgPSA0LCANCiAgICAgICAgICAgICAgIHN0cm9rZSA9IDEsDQogICAgICAgICAgICAgICBjb2xvcj0iYmxhY2siKSArDQogICAgdGhlbWVfYncoKSArICAgICAjIEN1c3RvbWl6ZSB0aGUgcGxvdA0KICAgIGxhYnMoeSA9ICJsblZSIiwgeCA9ICIiKSArDQogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzczQjcwNiIsICIjMDZBMkJBIiwgIiNCOTA2NzQiKSkrDQogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiM3M0I3MDYiLCAiIzA2QTJCQSIsICIjQjkwNjc0IikpICsgIA0KICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNCksDQogICAgICAgICAgYXhpcy50ZXh0LnkgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDEwLCANCiAgICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCBoanVzdCA9IDAuNSksDQogICAgICAgICAgYXhpcy50ZXh0LnggPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIwKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvciA9ICJub25lIikrDQogICAgY29vcmRfZmxpcCgpKw0KICAgIHhsaW0oLTAuNDUsIDAuNDUpICsNCiAgICBmYWNldF93cmFwKH50cmFpdF90eXBlLCBuY29sID0gMykrDQogICBzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cyA9IHJldihsZXZlbHMoYXMuZmFjdG9yKGxvb19yZXN1bHRzX2xuVlIkc3R1ZHlfaWQpKSkpICMgQWxwaGFiZXRpY2FsIG9yZGVyDQoNCmdnc2F2ZShmaWxlID0gImZpZy9sblZSX0xPTy5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSAxMiwgZHBpID0gNTAwKQ0KYGBgIA0KDQojIyMgKipVbnVzdWFsIHN0dWR5IGRlc2lnbnMqKiANCg0KIyMjIyAqTW9kZWwgc3BlY2lmaWNhdGlvbioNCmBgYHtyLCBldmFsID0gRn0NCiMgRGlzY2FyZCBvYnNlcnZhdGlvbnMgZmxhZ2dlZCBiZWNhdXNlIHRoZSBudW1iZXIgb2YgZ2VuZXJhdGlvbnMgb2Ygc2VsZWN0aW9uIHdhcyB1bmNsZWFyLCBhcyB0aGlzIHdvdWxkIG9ubHkgYWZmZWN0IHRoZSByZXN1bHRzIG9mIG1ldGEtcmVncmVzc2lvbnMNCmRhdGEgPC0gbXV0YXRlKGRhdGEsIG1pbm9yX2NvbmNlcm5zMiA9IGlmZWxzZShtaW5vcl9jb25jZXJucyA9PSAiZ2VuX3NlbGVjdGlvbiBhcHByb3hpbWF0ZSIgfCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWlub3JfY29uY2VybnMgPT0gImdlbl9zZWxlY3Rpb24gdW5kZXJlc3RpbWF0ZWQiLA0KICAgICAgICAgICAgICAgICAgICAgTkEsIG1pbm9yX2NvbmNlcm5zKSkgIA0KDQojIEZpbHRlciB0byBkYXRhIHdpdGhvdXQgc291cmNlcyBvZiBwcm9jZWR1cmFsICBjb25jZXJucy4NCmRhdGFfY29uY2VybnMgPC0gZmlsdGVyKGRhdGEsIGlzLm5hKG1ham9yX2NvbmNlcm5zKT09VCAmIGlzLm5hKG1pbm9yX2NvbmNlcm5zMik9PVQpDQoNCiMgRHJvcCB0aXBzIHRoYXQgYXJlIG5vdCBpbiB0aGUgd2FybSBkYXRhc2V0DQp0aXBzX3RvX2Ryb3AgPC0gc2V0ZGlmZihwaHlsb190cmVlJHRpcC5sYWJlbCwgZGF0YV9jb25jZXJucyRwaHlsb2dlbnkpDQpwaHlsb190cmVlX2NvbmNlcm5zIDwtIGRyb3AudGlwKHBoeWxvX3RyZWUsIHRpcHNfdG9fZHJvcCkNCg0KIyBDb21wdXRlIHBoeWxvZ2VuZXRpYyBjb3JyZWxhdGlvbiBtYXRyaXgNCnBoeWxvX21hdHJpeF9jb25jZXJucyA8LSB2Y3YocGh5bG9fdHJlZV9jb25jZXJucywgY29yID0gVCkgICMgVGhlIHZjdiBmdW5jdGlvbiByZXR1cm5zIGEgdmFyaWFuY2UtY292YXJpYW5jZSBtYXRyaXgNCg0KIyBDb252ZXJ0IHRpYmJsZSB0byBkYXRhIGZyYW1lDQpkYXRhX2NvbmNlcm5zIDwtIGFzLmRhdGEuZnJhbWUoZGF0YV9jb25jZXJucykNCg0KIyBDYWxjdWxhdGUgVkNWIG1hdHJpeA0KVkNWX2xuVlJfY29uY2VybnMgPC0gdmNhbGModmkgPSB2YXJfbG5WUiwNCiAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RlciA9IHNoYXJlZF9jb250cm9sX0lELCANCiAgICAgICAgICAgICAgICAgICAgICAgcmhvID0gMC41LA0KICAgICAgICAgICAgICAgICAgICAgICBvYnMgPSBvYnMsDQogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhX2NvbmNlcm5zKSANCg0KIyBNb2RlbCBzcGVjaWZpY2F0aW9uDQpmb3JtdWxhIDwtIGJmKGxuVlIgfiAwICsgdHJhaXRfdHlwZTp3YXJtX2NvbGQgKyB0cmFpdF90eXBlOndhcm1fY29sZDphc3NheV90ZW1wX2RpZmYgKyAjIFNlcGFyYXRlIGVmZmVjdHMgYnkgdHJhaXQgdHlwZQ0KICAgICAgICAgICAgICAgICh0cmFpdF90eXBlLTF8cmVmKSArICMgQ29ycmVsYXRpb24gYmV0d2VlbiB0cmFpdHMgYW1vbmcgc3R1ZGllcw0KICAgICAgICAgICAgICAgICgxfHNwZWNpZXMpICsgIyBTcGVjaWVzLWxldmVsIHJhbmRvbSBlZmZlY3QNCiAgICAgICAgICAgICAgICAoMXxncihwaHlsb2dlbnksIGNvdiA9IHBoeWxvX21hdHJpeF9jb25jZXJucykpICsgIyBQaHlsb2dlbmV0aWMgcmVsYXRlZG5lc3MNCiAgICAgICAgICAgICAgICAoMXxleHBlcmltZW50X0lEKSArICMgRXhwZXJpbWVudC1sZXZlbCByYW5kb20gZWZmZWN0DQogICAgICAgICAgICAgICAgKDF8b2JzKSArICMgT2JzZXJ2YXRpb24tbGV2ZWwgcmFuZG9tIGVmZmVjdA0KICAgICAgICAgICAgICAgIGZjb3IoVkNWX2xuVlJfY29uY2VybnMpKSAjIFZhcmlhbmNlIGNvdmFyaWFuY2UgbWF0aXggb2YgY29ycmVsYXRlZCBzYW1wbGluZyB2YXJpYW5jZXMNCg0KIyBEZWZpbmUgcHJpb3JzDQpwcmlvciA9IGMoDQogIHByaW9yKGNvbnN0YW50KDEpLCBjbGFzcyA9ICJzaWdtYSIpDQopICMgQmVjYXVzZSB0aGUgcmVzaWR1YWwgdmFyaWFuY2UtY292YXJpYW5jZSBzdHJ1Y3R1cmUgaXMgc3BlY2lmaWVkIGluIGZjb3IsIHRoZXJlIGlzIG5vIG5lZWQgdG8gZXN0aW1hdGUgc2lnbWEgc28gaXQgaXMgbGVmdCBhcyBhIGNvbnN0YW50DQoNCiMgRml0IG1vZGVsDQpsblZSX21vZGVsX2NvbmNlcm5zIDwtIGJybShmb3JtdWxhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gZ2F1c3NpYW4oKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGFfY29uY2VybnMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhMiA9IGxpc3QocGh5bG9fbWF0cml4X2NvbmNlcm5zID0gcGh5bG9fbWF0cml4X2NvbmNlcm5zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVkNWX2xuVlJfY29uY2VybnMgPSBWQ1ZfbG5WUl9jb25jZXJucyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yID0gcHJpb3IsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KGFkYXB0X2RlbHRhID0gMC45OSwgbWF4X3RyZWVkZXB0aCA9IDE1KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlciA9IDQwMDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YXJtdXAgPSAyMDAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFpbnMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXMgPSA0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEyMykgDQojIFNhdmUgbW9kZWwNCnNhdmVSRFMobG5WUl9tb2RlbF9jb25jZXJucywgZmlsZSA9ICJSRGF0YS9sblZSX21vZGVsX2NvbmNlcm5zLnJkcyIpDQpgYGANCg0KIyMjIyAqTW9kZWwgc3VtbWFyeSoNCmBgYHtyfQ0KIyBMb2FkIG1vZGVsDQpsblZSX21vZGVsX2NvbmNlcm5zIDwtIHJlYWRSRFMoIlJEYXRhL2xuVlJfbW9kZWxfY29uY2VybnMucmRzIikNCg0KIyBEaXNwbGF5IG1vZGVsIG91dHB1dCANCnN1bW1hcnkobG5WUl9tb2RlbF9jb25jZXJucykNCg0KIyBDbGVhbmVkIG1vZGVsIG91dHB1dA0KYXMuZGF0YS5mcmFtZShmaXhlZihsblZSX21vZGVsX2NvbmNlcm5zLCBzdW1tYXJ5ID0gVFJVRSkpICU+JQ0KICAjIFJlbmFtZSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgZm9yIGNsZWFuZXIgZGlzcGxheQ0KICByb3duYW1lc190b19jb2x1bW4odmFyID0gIlBhcmFtZXRlciIpICU+JSANCiAgbXV0YXRlKA0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKyk6d2FybV9jb2xkKGNvbGR8d2FybSkiLCAiXFwxKFxcMikiLCBQYXJhbWV0ZXIpLA0KICAgIFBhcmFtZXRlciA9IGdzdWIoInRyYWl0X3R5cGUoW2Etel9dKylcXCh3YXJtXFwpOmFzc2F5X3RlbXBfZGlmZiIsICJcXDEod2FybSk6IGFzc2F5X3RlbXBfZGlmZiIsIFBhcmFtZXRlcikNCiAgKSAlPiUNCiAgIyBSb3VuZCBudW1iZXJzIHRvIDMgZGVjaW1hbCBwb2ludHMNCiAgbXV0YXRlKGFjcm9zcyhjKEVzdGltYXRlLCBRMi41LCBROTcuNSksIH4gcm91bmQoLiwgMykpKSAlPiUNCiAgc2VsZWN0KFBhcmFtZXRlciwgRXN0aW1hdGUsIGBMb3dlciBDSWAgPSBRMi41LCBgVXBwZXIgQ0lgID0gUTk3LjUpICU+JQ0KICBrYWJsZSgpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSwgcG9zaXRpb24gPSAiY2VudGVyIiwgZml4ZWRfdGhlYWQgPSBUUlVFKSAlPiUNCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUsIGJvcmRlcl9yaWdodCA9IFRSVUUpICU+JQ0KICByb3dfc3BlYygwLCBiYWNrZ3JvdW5kID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siLCBib2xkID0gVFJVRSkgJT4lDQogIGthYmxlX3N0eWxpbmcoZml4ZWRfdGhlYWQgPSBUUlVFKQ0KYGBgDQoNCiMjIyMgKkRhdGEgdmlzdWFsaXNhdGlvbiogDQpgYGB7ciwgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQ9MTB9DQojIERpc2NhcmQgb2JzZXJ2YXRpb25zIGZsYWdnZWQgYmVjYXVzZSB0aGUgbnVtYmVyIG9mIGdlbmVyYXRpb25zIG9mIHNlbGVjdGlvbiB3YXMgdW5jbGVhciwgYXMgdGhpcyB3b3VsZCBvbmx5IGFmZmVjdCB0aGUgcmVzdWx0cyBvZiBtZXRhLXJlZ3Jlc3Npb25zDQpkYXRhIDwtIG11dGF0ZShkYXRhLCBtaW5vcl9jb25jZXJuczIgPSBpZmVsc2UobWlub3JfY29uY2VybnMgPT0gImdlbl9zZWxlY3Rpb24gYXBwcm94aW1hdGUiIHwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbm9yX2NvbmNlcm5zID09ICJnZW5fc2VsZWN0aW9uIHVuZGVyZXN0aW1hdGVkIiwNCiAgICAgICAgICAgICAgICAgICAgIE5BLCBtaW5vcl9jb25jZXJucykpIA0KDQojIEZpbHRlciB0byBkYXRhIHdpdGhvdXQgc291cmNlcyBvZiBwcm9jZWR1cmFsICBjb25jZXJucy4NCmRhdGFfY29uY2VybnMgPC0gZmlsdGVyKGRhdGEsIGlzLm5hKG1ham9yX2NvbmNlcm5zKT09VCAmIGlzLm5hKG1pbm9yX2NvbmNlcm5zMik9PVQpDQoNCiMgQ2FsY3VsYXRlIHNhbXBsZSBzaXplcyBhbmQgc3R1ZHkgY291bnRzDQpzYW1wbGVfc2l6ZXNfY29uY2VybnMgPC0gZGF0YV9jb25jZXJucyAlPiUNCiAgZ3JvdXBfYnkodHJhaXRfdHlwZSwgd2FybV9jb2xkKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGVzdGltYXRlcyA9IG4oKSwNCiAgICBzdHVkaWVzID0gbl9kaXN0aW5jdChyZWYpDQogICkNCg0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucw0KZW1tZWFuc19jb25jZXJucyA8LSBhcy5kYXRhLmZyYW1lKGVtbWVhbnMoDQogIGxuVlJfbW9kZWxfY29uY2VybnMsDQogIHNwZWNzID0gfiBhc3NheV90ZW1wX2RpZmYgfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3QoYXNzYXlfdGVtcF9kaWZmID0gc2VxKG1pbihkYXRhX2NvbmNlcm5zJGFzc2F5X3RlbXBfZGlmZiksIG1heChkYXRhX2NvbmNlcm5zJGFzc2F5X3RlbXBfZGlmZiksIGJ5ID0gMC41KSkpKQ0KDQojIENhbGN1bGF0ZSByYW5nZSBvZiB2YWx1ZXMgZm9yIGVhY2ggY2F0ZWdvcnkNCnJhbmdlX2RmX2NvbmNlcm5zIDwtIGRhdGFfY29uY2VybnMgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtaW5fYXNzYXlfdGVtcF9kaWZmID0gbWluKGFzc2F5X3RlbXBfZGlmZiksDQogICAgbWF4X2Fzc2F5X3RlbXBfZGlmZiA9IG1heChhc3NheV90ZW1wX2RpZmYpDQogICkNCg0KZW1tZWFuc19jb25jZXJucyR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX2NvbmNlcm5zJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfY29uY2VybnMkd2FybV9jb2xkIDwtIGZhY3RvcihlbW1lYW5zX2NvbmNlcm5zJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgVGFpbG9yIHByZWRpY3Rpb25zIHRvIHRoZSByYW5nZSBvZiB0aGUgZGF0YQ0KZW1tZWFuc19jb25jZXJucyA8LSBlbW1lYW5zX2NvbmNlcm5zICU+JQ0KICBsZWZ0X2pvaW4ocmFuZ2VfZGZfY29uY2VybnMsIGJ5ID0gYygidHJhaXRfdHlwZSIsICJ3YXJtX2NvbGQiKSkgJT4lDQogIGZpbHRlcigNCiAgICBhc3NheV90ZW1wX2RpZmYgPj0gbWluX2Fzc2F5X3RlbXBfZGlmZiwNCiAgICBhc3NheV90ZW1wX2RpZmYgPD0gbWF4X2Fzc2F5X3RlbXBfZGlmZg0KICApDQoNCiMgUGxvdA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArICANCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCAjIFZlcnRpY2FsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSkgKyANCiAgICBnZW9tX3BvaW50KGRhdGEgPSBkYXRhX2NvbmNlcm5zLCAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBhc3NheV90ZW1wX2RpZmYsIA0KICAgICAgICAgICAgICAgICAgICAgIHkgPSBsblZSLCANCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMS9zcXJ0KHZhcl9sblZSKSwgDQogICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwgDQogICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNywgDQogICAgICAgICAgICAgICAgICBzdHJva2UgPSAxLA0KICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjA1KSkgKyANCiAgICAgZ2VvbV9yaWJib24oZGF0YSA9IGVtbWVhbnNfY29uY2VybnMsICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IGFzc2F5X3RlbXBfZGlmZiwNCiAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICBmaWxsID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgYWxwaGEgPSAuNSkgKyANCiAgICAgZ2VvbV9saW5lKGRhdGEgPSBlbW1lYW5zX2NvbmNlcm5zLCAgIyBQcmVkaWN0ZWQgcmVncmVzc2lvbiBsaW5lDQogICAgICAgICAgICAgICBhZXMoeSA9IGVtbWVhbiwNCiAgICAgICAgICAgICAgICAgICB4ID0gYXNzYXlfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArIA0KICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzX2NvbmNlcm5zLCANCiAgICAgICAgICAgICAgYWVzKHggPSBJbmYsIA0KICAgICAgICAgICAgICAgICAgeSA9IGlmZWxzZSh3YXJtX2NvbGQgPT0gIldhcm0iLCAtMiwgLTIuNzUpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICANCiAgZmFjZXRfd3JhcCh+IHRyYWl0X3R5cGUsIG5jb2wgPSAxKSArICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJBc3NheSB0ZW1wZXJhdHVyZSBkaWZmZXJlbmNlIiwgeSA9ICJsblZSIiwNCiAgICAgICBjb2wgPSAiUmVnaW1lIikgKw0KICB0aGVtZV9idygpICsgDQogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgOCkpKyANCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjUsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxOCksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAyMikpICsNCiAgICBndWlkZXMoZmlsbCA9ICJub25lIiwgc2l6ZSA9ICJub25lIikrDQogICAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0zLjUsIDMuNSkpDQoNCmdnc2F2ZShmaWxlID0gImZpZy9sblZSX2NvbmNlcm5zLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDcsIGRwaSA9IDUwMCkNCmBgYA0KDQojICoqRmlndXJlcyBmb3IgcHVibGljYXRpb24qKiANCg0KTm90ZSB0aGF0IEZpZ3VyZSAxIHdhcyBjcmVhdGVkIHdpdGhvdXQgY29kZS4NCg0KIyMgKipGaWd1cmUgMioqDQpgYGB7ciwgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQgPSAxMH0NCiMgTWF0Y2ggc3BlY2llcyB0byB0aGUgT1RMIGRhdGFiYXNlDQpyZXNvbHZlZF9uYW1lcyA8LSB0bnJzX21hdGNoX25hbWVzKHVuaXF1ZShkYXRhJHNwZWNpZXMpLCBjb250ZXh0X25hbWUgPSAiQW5pbWFscyIpDQoNCiMgQ3JlYXRlIHRyZWUNCnRyZWUgPC0gdG9sX2luZHVjZWRfc3VidHJlZShvdHRfaWRzID0gcmVzb2x2ZWRfbmFtZXMkb3R0X2lkKQ0KdHJlZSR0aXAubGFiZWwgPC0gc3RyaXBfb3R0X2lkcyh0cmVlJHRpcC5sYWJlbCkgIyBSZW1vdmUgb3R0IElEcyBmb3IgcHJlc2VudGF0aW9uDQoNCnRyZWUgPC0gbXVsdGkyZGkodHJlZSwgcmFuZG9tID0gVFJVRSkgIyBSZXNvbHZlIHBvbHl0b215IGF0IHJhbmRvbSwgYnV0IGl0IG1hdGNoZXMgY2xhc3NpZmljYXRpb24gZnJvbSBDb3JuZXR0aSBldCBhbC4gMjAxOS4gTW9sZWN1bGFyIFBoeWxvZ2VuZXRpY3MgYW5kIEV2b2x1dGlvbjsgd2l0aCBELiBwdWxleCBhbmQgRC4gcHVsaWNhcmlhIGJlaW5nIG1vcmUgY2xvc2VseSByZWxhdGVkIHRvIGVhY2hvdGhlciB0aGFuIEQuIG1hZ25hDQpwaHlsb190cmVlIDwtIGNvbXB1dGUuYnJsZW4odHJlZSwgbWV0aG9kID0gIkdyYWZlbiIsIHBvd2VyID0gMSkgIyBDb21wdXRlIGJyYW5jaCBsZW5ndGhzDQoNCiMgUmVtb3ZlIHVuZGVyc2NvcmUgZm9yIHNwZWNpZXMgbmFtZXMNCnBoeWxvX3RyZWUkdGlwLmxhYmVsIDwtIGdzdWIoIl8iLCAiICIsIHBoeWxvX3RyZWUkdGlwLmxhYmVsKSAjIEFkZCB1bmRlcnNjb3JlIGJldHdlZW4gc3BlY2llcyBuYW1lcw0KDQojIENyZWF0ZSBhIGRhdGEgc3VtbWFyeSBmb3IgZWFjaCBzcGVjaWVzDQpzcGVjaWVzX3N1bW1hcnkgPC0gZGF0YSAlPiUNCiAgZ3JvdXBfYnkodGlwLmxhYmVsID0gc3BlY2llcywgd2FybV9jb2xkKSAlPiUNCiAgc3VtbWFyaXNlKG5fZWZmZWN0X3NpemVzID0gbigpLCAuZ3JvdXBzID0gImRyb3AiKSANCg0Kc3BlY2llc190b3RhbHMgPC0gc3BlY2llc19zdW1tYXJ5ICU+JQ0KICBncm91cF9ieSh0aXAubGFiZWwpICU+JQ0KICBzdW1tYXJpc2UodG90YWxfZWZmZWN0X3NpemVzID0gc3VtKG5fZWZmZWN0X3NpemVzKSwgLmdyb3VwcyA9ICJkcm9wIikNCg0KIyBPcmRlciBzcGVjaWVzDQpzcGVjaWVzX29yZGVyIDwtIHJldihjKA0KICAiRHJvc29waGlsYSBiaXBlY3RpbmF0YSIsDQogICJEcm9zb3BoaWxhIHBzZXVkb2FuYW5hc3NhZSIsDQogICJEcm9zb3BoaWxhIG1lbGFub2dhc3RlciIsDQogICJEcm9zb3BoaWxhIHNlcnJhdGEiLA0KICAiRHJvc29waGlsYSBzdWJvYnNjdXJhIiwNCiAgIkRyb3NvcGhpbGEgaHlkZWkiLA0KICAiRHJvc29waGlsYSBidXp6YXRpaSIsDQogICJNdXNjYSBkb21lc3RpY2EiLA0KICAiU2Vwc2lzIHB1bmN0dW0iLA0KICAiQ2FsbG9zb2JydWNodXMgY2hpbmVuc2lzIiwNCiAgIkNhbGxvc29icnVjaHVzIG1hY3VsYXR1cyIsDQogICJaYWJyb3RlcyBzdWJmYXNjaWF0dXMiLA0KICAiVHJpYm9saXVtIGNhc3RhbmV1bSIsDQogICJEYXBobmlhIHB1bGljYXJpYSIsDQogICJEYXBobmlhIHB1bGV4IiwNCiAgIkRhcGhuaWEgbWFnbmEiLA0KICAiU2ltb2NlcGhhbHVzIHZldHVsdXMiLA0KICAiQXBvY3ljbG9wcyByb3lpIiwNCiAgIkV1cnl0ZW1vcmEgYWZmaW5pcyIsDQogICJSaGl6b2dseXBodXMgcm9iaW5pIiwNCiAgIkNhZW5vcmhhYmRpdGlzIHJlbWFuZWkiLA0KICAiT3BocnlvdHJvY2hhIGxhYnJvbmljYSIsDQogICJCcmFjaGlvbnVzIHBsaWNhdGlsaXMiLA0KICAiUG9lY2lsaWEgcmV0aWN1bGF0YSIsDQogICJEYW5pbyByZXJpbyINCikpDQoNCnNwZWNpZXNfc3VtbWFyeSA8LSBzcGVjaWVzX3N1bW1hcnkgJT4lDQogIG11dGF0ZSh0aXAubGFiZWwgPSBmYWN0b3IodGlwLmxhYmVsLCBsZXZlbHMgPSBzcGVjaWVzX29yZGVyKSkNCg0KIyBQbG90IHRyZWUNCnRyZWVfcGxvdCA8LSBnZ3RyZWUocGh5bG9fdHJlZSwgbHdkID0gMS4yNSkgKw0KICBnZW9tX3RpcGxhYihzaXplID0gNSwNCiAgICAgICAgICAgICAgb2Zmc2V0ID0gMC4wNzUsDQogICAgICAgICAgICAgIGZvbnRmYWNlID0gIml0YWxpYyIpICsgDQogIHhsaW0oMCwgMi41KSArIA0KICB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAxLjUsIDAsIDApLCAiY20iKSkNCg0KYmFycGxvdCA8LSBnZ3Bsb3Qoc3BlY2llc19zdW1tYXJ5LCBhZXMoeCA9IHRpcC5sYWJlbCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gbl9lZmZlY3Rfc2l6ZXMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIA0KICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlMigpLCANCiAgICAgICAgICAgd2lkdGggPSAwLjgpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgDQogICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCANCiAgICAgICAgICAgICBzaXplID0gMC43NSkgKyAgIyBBZGQgdmVydGljYWwgbGluZQ0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLjQsIA0KICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwgDQogICAgICAgICAgICAgc2l6ZSA9IDAuNSkgKyAgIyBBZGQgaG9yaXpvbnRhbCBsaW5lDQogIGdlb21fdGV4dChkYXRhID0gc3BlY2llc190b3RhbHMsIA0KICAgICAgICAgICAgYWVzKHggPSB0aXAubGFiZWwsIA0KICAgICAgICAgICAgICAgIHkgPSAtOCwgDQogICAgICAgICAgICAgICAgbGFiZWwgPSB0b3RhbF9lZmZlY3Rfc2l6ZXMpLCANCiAgICAgICAgICAgIGluaGVyaXQuYWVzID0gRkFMU0UsIA0KICAgICAgICAgICAgc2l6ZSA9IDUpICsgICMgQWRkIHRvdGFsIGNvdW50IGFubm90YXRpb24NCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiQ29sZCIgPSAiIzA2QjRCQSIsICJXYXJtIiA9ICIjRTgwNzU2IikpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLjA1LCAwLjIpKSkgKyAgIyBBZGQgc3BhY2Ugb24gdGhlIHJpZ2h0DQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnMoeCA9IE5VTEwsIHkgPSAiTnVtYmVyIG9mIGVmZmVjdCBzaXplcyIpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksICAjIFJlbW92ZSB5LWF4aXMgdGV4dCBmb3IgYWxpZ25tZW50DQogICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwgICMgUmVtb3ZlIGdyaWQNCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvciA9IE5BKSwgICMgV2hpdGUgYmFja2dyb3VuZA0KICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dCAoc2l6ZSA9IDE0KSwgY29sID0gImJsYWNrIiwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgpKQ0KDQoNCnRyZWVfcGxvdCB8IGJhcnBsb3QNCg0KZ2dzYXZlKGZpbGUgPSAiZmlnL2ZpZ3VyZV8yLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDEwLCBkcGkgPSA1MDApDQoNCmBgYA0KDQojIyAqKkZpZ3VyZSAzKiogDQoNCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD0xMH0NCiMgTG9hZCBtb2RlbA0KbG5SUl9tb2RlbF9hc3NheV90ZW1wX2RpZmYgPC0gcmVhZFJEUygiUkRhdGEvbG5SUl9tb2RlbF9hc3NheV90ZW1wX2RpZmYucmRzIikNCg0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucw0KZW1tZWFuc19hc3NheV90ZW1wX2RpZmYgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsblJSX21vZGVsX2Fzc2F5X3RlbXBfZGlmZiwNCiAgc3BlY3MgPSB+IGFzc2F5X3RlbXBfZGlmZiB8IHRyYWl0X3R5cGUgKiB3YXJtX2NvbGQsDQogIGF0ID0gbGlzdChhc3NheV90ZW1wX2RpZmYgPSBzZXEobWluKGRhdGEkYXNzYXlfdGVtcF9kaWZmKSwgbWF4KGRhdGEkYXNzYXlfdGVtcF9kaWZmKSwgYnkgPSAwLjUpKSkNCiAgKQ0KDQojIENhbGN1bGF0ZSByYW5nZSBvZiB2YWx1ZXMgZm9yIGVhY2ggY2F0ZWdvcnkNCnJhbmdlX2RmIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtaW5fYXNzYXlfdGVtcF9kaWZmID0gbWluKGFzc2F5X3RlbXBfZGlmZiksDQogICAgbWF4X2Fzc2F5X3RlbXBfZGlmZiA9IG1heChhc3NheV90ZW1wX2RpZmYpDQogICkNCg0KZW1tZWFuc19hc3NheV90ZW1wX2RpZmYkdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19hc3NheV90ZW1wX2RpZmYkdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KZW1tZWFuc19hc3NheV90ZW1wX2RpZmYkd2FybV9jb2xkIDwtIGZhY3RvcihlbW1lYW5zX2Fzc2F5X3RlbXBfZGlmZiR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KDQojIFRhaWxvciBwcmVkaWN0aW9ucyB0byB0aGUgcmFuZ2Ugb2YgdGhlIGRhdGENCmVtbWVhbnNfYXNzYXlfdGVtcF9kaWZmIDwtIGVtbWVhbnNfYXNzYXlfdGVtcF9kaWZmICU+JQ0KICBsZWZ0X2pvaW4ocmFuZ2VfZGYsIGJ5ID0gYygidHJhaXRfdHlwZSIsICJ3YXJtX2NvbGQiKSkgJT4lDQogIGZpbHRlcigNCiAgICBhc3NheV90ZW1wX2RpZmYgPj0gbWluX2Fzc2F5X3RlbXBfZGlmZiwNCiAgICBhc3NheV90ZW1wX2RpZmYgPD0gbWF4X2Fzc2F5X3RlbXBfZGlmZg0KICApDQoNCiMgUGxvdA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArICANCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCAjIFZlcnRpY2FsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSkgKyAgDQogICAgZ2VvbV9wb2ludChkYXRhID0gZGF0YSwgIyBFZmZlY3Qgc2l6ZXMsIHNjYWxlZCBieSBwcmVjaXNpb24NCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gYXNzYXlfdGVtcF9kaWZmLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5SUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5SUiksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX2Fzc2F5X3RlbXBfZGlmZiwgIyBTaGFkZWQgYXJlYSBmb3IgY3JlZGlibGUgaW50ZXJ2YWxzDQogICAgICAgICAgICAgICAgIGFlcyh4ID0gYXNzYXlfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICBhbHBoYSA9IC41KSArIA0KICAgICBnZW9tX2xpbmUoZGF0YSA9IGVtbWVhbnNfYXNzYXlfdGVtcF9kaWZmLCAgIyBQcmVkaWN0ZWQgcmVncmVzc2lvbiBsaW5lDQogICAgICAgICAgICAgICBhZXMoeSA9IGVtbWVhbiwNCiAgICAgICAgICAgICAgICAgICB4ID0gYXNzYXlfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArIA0KICAgICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXMsIA0KICAgICAgICAgICAgICBhZXMoeCA9IEluZiwgDQogICAgICAgICAgICAgICAgICB5ID0gaWZlbHNlKHdhcm1fY29sZCA9PSAiV2FybSIsIC0wLjksIC0xLjMpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICANCiAgZmFjZXRfd3JhcCh+IHRyYWl0X3R5cGUsIG5jb2wgPSAxKSArICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJBc3NheSB0ZW1wZXJhdHVyZSBkaWZmZXJlbmNlIiwgeSA9ICJsblJSIiwgY29sID0gIlJlZ2ltZSIpICsNCiAgdGhlbWVfYncoKSArIA0KICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDQsIDEwKSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNSwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDIyKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiKSsNCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTEuNSwgMS41KSkNCg0KZ2dzYXZlKGZpbGUgPSAiZmlnL2ZpZ3VyZV8zLnBuZyIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDEwLCBkcGkgPSA1MDApDQpgYGANCg0KIyMgKipGaWd1cmUgNCoqIA0KDQpgYGB7ciwgZmlnLndpZHRoID0gMjAsIGZpZy5oZWlnaHQgPSAzMn0NCiMgTG9hZCBtb2RlbHMNCmxuUlJfbW9kZWxfc2VsX3RlbXBfZGlmZiA8LSByZWFkUkRTKCJSRGF0YS9sblJSX21vZGVsX3NlbF90ZW1wX2RpZmYucmRzIikNCmxuUlJfbW9kZWxfZ2VuX3NlbGVjdGlvbiA8LSByZWFkUkRTKCJSRGF0YS9sblJSX21vZGVsX2dlbl9zZWxlY3Rpb24ucmRzIikNCmxuUlJfbW9kZWxfZ2VuX2NvbW1vbl9nYXJkZW4gPC0gcmVhZFJEUygiUkRhdGEvbG5SUl9tb2RlbF9nZW5fY29tbW9uX2dhcmRlbi5yZHMiKQ0KbG5SUl9tb2RlbF9wb3Bfc2l6ZSA8LSByZWFkUkRTKCJSRGF0YS9sblJSX21vZGVsX3BvcF9zaXplLnJkcyIpDQpsblJSX21vZGVsX2FsbF9tb2RlcmF0b3JzIDwtIHJlYWRSRFMoIlJEYXRhL2xuUlJfbW9kZWxfYWxsX21vZGVyYXRvcnMucmRzIikNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIFNlbGVjdGlvbiB0ZW1wZXJhdHVyZSAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQojIEdlbmVyYXRlIHByZWRpY3Rpb25zDQplbW1lYW5zX3NlbF90ZW1wX2RpZmYgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsblJSX21vZGVsX3NlbF90ZW1wX2RpZmYsDQogIHNwZWNzID0gfiBzZWxlY3RfdGVtcF9kaWZmIHwgdHJhaXRfdHlwZSAqIHdhcm1fY29sZCwNCiAgYXQgPSBsaXN0KHNlbGVjdF90ZW1wX2RpZmYgPSBzZXEobWluKGRhdGEkc2VsZWN0X3RlbXBfZGlmZiksIG1heChkYXRhJHNlbGVjdF90ZW1wX2RpZmYpLCBieSA9IDAuMSksDQogICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPSAwKSkNCiAgKSAjIENvbmRpdGlvbmFsIGVmZmVjdHMgb24gYXNzYXlfdGVtcF9kaWZmID0gMA0KDQojIENhbGN1bGF0ZSByYW5nZSBvZiB2YWx1ZXMgZm9yIGVhY2ggY2F0ZWdvcnkNCnJhbmdlX2RmIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtaW5fc2VsZWN0X3RlbXBfZGlmZiA9IG1pbihzZWxlY3RfdGVtcF9kaWZmKSwNCiAgICBtYXhfc2VsZWN0X3RlbXBfZGlmZiA9IG1heChzZWxlY3RfdGVtcF9kaWZmKQ0KICApDQoNCmVtbWVhbnNfc2VsX3RlbXBfZGlmZiR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX3NlbF90ZW1wX2RpZmYkdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KZW1tZWFuc19zZWxfdGVtcF9kaWZmJHdhcm1fY29sZCA8LSBmYWN0b3IoZW1tZWFuc19zZWxfdGVtcF9kaWZmJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgVGFpbG9yIHByZWRpY3Rpb25zIHRvIHRoZSByYW5nZSBvZiB0aGUgZGF0YQ0KZW1tZWFuc19zZWxfdGVtcF9kaWZmIDwtIGVtbWVhbnNfc2VsX3RlbXBfZGlmZiAlPiUNCiAgbGVmdF9qb2luKHJhbmdlX2RmLCBieSA9IGMoInRyYWl0X3R5cGUiLCAid2FybV9jb2xkIikpICU+JQ0KICBmaWx0ZXIoDQogICAgc2VsZWN0X3RlbXBfZGlmZiA+PSBtaW5fc2VsZWN0X3RlbXBfZGlmZiwNCiAgICBzZWxlY3RfdGVtcF9kaWZmIDw9IG1heF9zZWxlY3RfdGVtcF9kaWZmDQogICkNCg0KIyBQbG90DQpzZWxfdGVtcF9kaWZmIDwtIA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsICAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBzZWxlY3RfdGVtcF9kaWZmLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5SUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5SUiksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX3NlbF90ZW1wX2RpZmYsICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IHNlbGVjdF90ZW1wX2RpZmYsDQogICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgIGFscGhhID0gLjUpICsgDQogICAgIGdlb21fbGluZShkYXRhID0gZW1tZWFuc19zZWxfdGVtcF9kaWZmLCAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSBzZWxlY3RfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArICANCiAgICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXMsIA0KICAgICAgICAgICAgICBhZXMoeCA9IEluZiwgDQogICAgICAgICAgICAgICAgICB5ID0gaWZlbHNlKHdhcm1fY29sZCA9PSAiV2FybSIsIC0wLjksIC0xLjMpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBmYWNldF93cmFwKH4gdHJhaXRfdHlwZSwgbmNvbCA9IDEpICsgICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJTZWxlY3Rpb24gdGVtcGVyYXR1cmUgZGlmZmVyZW5jZSIsIHkgPSAibG5SUiIsIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYyg0LCAxMCkpKyANCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMzAsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxOCksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAyOCksDQogICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDEsIDAsIDAsIDApLCAiY20iKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiLCBjb2xvciA9ICJub25lIikrDQogICAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0xLjUsIDEuNSkpDQoNCiMjIyMjIyMjIyMjIyMjIEdlbmVyYXRpb25zIG9mIHNlbGVjdGlvbiAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbWVhbnNfZ2VuX3NlbGVjdGlvbiA8LSBhcy5kYXRhLmZyYW1lKGVtbWVhbnMoDQogIGxuUlJfbW9kZWxfZ2VuX3NlbGVjdGlvbiwNCiAgc3BlY3MgPSB+IGdlbl9zZWxlY3Rpb24gfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3QoZ2VuX3NlbGVjdGlvbiA9IHNlcShtaW4oZGF0YSRnZW5fc2VsZWN0aW9uKSwgbWF4KGRhdGEkZ2VuX3NlbGVjdGlvbiksIGJ5ID0gMSksDQogICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPSAwKSkNCiAgKSAjIENvbmRpdGlvbmFsIGVmZmVjdHMgb24gYXNzYXlfdGVtcF9kaWZmID0gMA0KDQojIENhbGN1bGF0ZSByYW5nZSBvZiB2YWx1ZXMgZm9yIGVhY2ggY2F0ZWdvcnkNCnJhbmdlX2RmIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtaW5fZ2VuX3NlbGVjdGlvbiA9IG1pbihnZW5fc2VsZWN0aW9uKSwNCiAgICBtYXhfZ2VuX3NlbGVjdGlvbiA9IG1heChnZW5fc2VsZWN0aW9uKQ0KICApDQoNCmVtbWVhbnNfZ2VuX3NlbGVjdGlvbiR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX2dlbl9zZWxlY3Rpb24kdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KZW1tZWFuc19nZW5fc2VsZWN0aW9uJHdhcm1fY29sZCA8LSBmYWN0b3IoZW1tZWFuc19nZW5fc2VsZWN0aW9uJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgVGFpbG9yIHByZWRpY3Rpb25zIHRvIHRoZSByYW5nZSBvZiB0aGUgZGF0YQ0KZW1tZWFuc19nZW5fc2VsZWN0aW9uIDwtIGVtbWVhbnNfZ2VuX3NlbGVjdGlvbiAlPiUNCiAgbGVmdF9qb2luKHJhbmdlX2RmLCBieSA9IGMoInRyYWl0X3R5cGUiLCAid2FybV9jb2xkIikpICU+JQ0KICBmaWx0ZXIoDQogICAgZ2VuX3NlbGVjdGlvbiA+PSBtaW5fZ2VuX3NlbGVjdGlvbiwNCiAgICBnZW5fc2VsZWN0aW9uIDw9IG1heF9nZW5fc2VsZWN0aW9uDQogICkNCg0KIyBQbG90DQpnZW5fc2VsZWN0aW9uIDwtIA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsICAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBnZW5fc2VsZWN0aW9uLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5SUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5SUiksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX2dlbl9zZWxlY3Rpb24sICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IGdlbl9zZWxlY3Rpb24sDQogICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgIGFscGhhID0gLjUpICsgDQogICAgIGdlb21fbGluZShkYXRhID0gZW1tZWFuc19nZW5fc2VsZWN0aW9uLCAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSBnZW5fc2VsZWN0aW9uLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArICANCiAgICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXMsIA0KICAgICAgICAgICAgICBhZXMoeCA9IEluZiwgDQogICAgICAgICAgICAgICAgICB5ID0gaWZlbHNlKHdhcm1fY29sZCA9PSAiV2FybSIsIC0wLjksIC0xLjMpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBmYWNldF93cmFwKH4gdHJhaXRfdHlwZSwgbmNvbCA9IDEpICsgICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJOdW1iZXIgIG9mIGdlbmVyYXRpb25zIG9mIHNlbGVjdGlvbiIsIHkgPSAibG5SUiIsIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYyg0LCAxMCkpKyANCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMzAsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxOCksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAyOCksDQogICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDEuNSwgMCwgMCwgMCksICJjbSIpKSArDQogICAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIHNpemUgPSAibm9uZSIsIGNvbG9yID0gIm5vbmUiKSsNCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTEuNSwgMS41KSwNCiAgICAgICAgICAgICAgICAgICAgeGxpbSA9IGMoMCwgMTUwKSkNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIEdlbmVyYXRpb25zIG9mIGNvbW1vbiBnYXJkZW4gIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4gPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsblJSX21vZGVsX2dlbl9jb21tb25fZ2FyZGVuLA0KICBzcGVjcyA9IH4gZ2VuX2NvbW1vbl9nYXJkZW4gfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3QoZ2VuX2NvbW1vbl9nYXJkZW4gPSBzZXEobWluKGRhdGEkZ2VuX2NvbW1vbl9nYXJkZW4pLCBtYXgoZGF0YSRnZW5fY29tbW9uX2dhcmRlbiksIGJ5ID0gMSksDQogICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPSAwKSkNCiAgKSAjIENvbmRpdGlvbmFsIGVmZmVjdHMgb24gYXNzYXlfdGVtcF9kaWZmID0gMA0KDQojIENhbGN1bGF0ZSByYW5nZSBvZiB2YWx1ZXMgZm9yIGVhY2ggY2F0ZWdvcnkNCnJhbmdlX2RmIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtaW5fZ2VuX2NvbW1vbl9nYXJkZW4gPSBtaW4oZ2VuX2NvbW1vbl9nYXJkZW4pLA0KICAgIG1heF9nZW5fY29tbW9uX2dhcmRlbiA9IG1heChnZW5fY29tbW9uX2dhcmRlbikNCiAgKQ0KDQplbW1lYW5zX2dlbl9jb21tb25fZ2FyZGVuJHRyYWl0X3R5cGUgPC0gZmFjdG9yKGVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4kdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KZW1tZWFuc19nZW5fY29tbW9uX2dhcmRlbiR3YXJtX2NvbGQgPC0gZmFjdG9yKGVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4kd2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiY29sZCIsICJ3YXJtIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJDb2xkIiwgIldhcm0iKSkNCg0KIyBUYWlsb3IgcHJlZGljdGlvbnMgdG8gdGhlIHJhbmdlIG9mIHRoZSBkYXRhDQplbW1lYW5zX2dlbl9jb21tb25fZ2FyZGVuIDwtIGVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4gJT4lDQogIGxlZnRfam9pbihyYW5nZV9kZiwgYnkgPSBjKCJ0cmFpdF90eXBlIiwgIndhcm1fY29sZCIpKSAlPiUNCiAgZmlsdGVyKA0KICAgIGdlbl9jb21tb25fZ2FyZGVuID49IG1pbl9nZW5fY29tbW9uX2dhcmRlbiwNCiAgICBnZW5fY29tbW9uX2dhcmRlbiA8PSBtYXhfZ2VuX2NvbW1vbl9nYXJkZW4NCiAgKQ0KDQojIFBsb3QNCmdlbl9jb21tb25fZ2FyZGVuIDwtIA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsICAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBnZW5fY29tbW9uX2dhcmRlbiwgDQogICAgICAgICAgICAgICAgICAgICAgeSA9IGxuUlIsIA0KICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxL3NxcnQodmFyX2xuUlIpLCANCiAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgICBzaGFwZSA9IDIxLCANCiAgICAgICAgICAgICAgICAgIGFscGhhID0gMC43LCANCiAgICAgICAgICAgICAgICAgIHN0cm9rZSA9IDEsDQogICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IDAuMDUpKSArIA0KICAgICBnZW9tX3JpYmJvbihkYXRhID0gZW1tZWFuc19nZW5fY29tbW9uX2dhcmRlbiwgIyBTaGFkZWQgYXJlYSBmb3IgY3JlZGlibGUgaW50ZXJ2YWxzDQogICAgICAgICAgICAgICAgIGFlcyh4ID0gZ2VuX2NvbW1vbl9nYXJkZW4sDQogICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgIGFscGhhID0gLjUpICsgDQogICAgIGdlb21fbGluZShkYXRhID0gZW1tZWFuc19nZW5fY29tbW9uX2dhcmRlbiwgIyBQcmVkaWN0ZWQgcmVncmVzc2lvbiBsaW5lDQogICAgICAgICAgICAgICBhZXMoeSA9IGVtbWVhbiwNCiAgICAgICAgICAgICAgICAgICB4ID0gZ2VuX2NvbW1vbl9nYXJkZW4sDQogICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsgIA0KICAgICBnZW9tX3RleHQoZGF0YSA9IHNhbXBsZV9zaXplcywgDQogICAgICAgICAgICAgIGFlcyh4ID0gSW5mLCANCiAgICAgICAgICAgICAgICAgIHkgPSBpZmVsc2Uod2FybV9jb2xkID09ICJXYXJtIiwgLTAuOSwgLTEuMyksICAjIFNhbXBsZSBzaXplcw0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEuMDUsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGZhY2V0X3dyYXAofiB0cmFpdF90eXBlLCBuY29sID0gMSkgKyAgIyBEaWZmZXJlbnQgcGFuZWxzIGZvciBlYWNoIHRyYWl0DQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgbGFicyh4ID0gIk51bWJlciBvZiBnZW5lcmF0aW9ucyBvZiBjb21tb24gZ2FyZGVuIiwgeSA9ICIiLCBjb2wgPSAiUmVnaW1lIikgKw0KICB0aGVtZV9idygpICsgDQogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoNCwgMTApKSsgDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDMwLCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTgpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgICAgYXhpcy50ZXh0LnkgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwLCANCiAgICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCBoanVzdCA9IDAuNSksDQogICAgICAgICAgYXhpcy50ZXh0LnggPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuNSksDQogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMjgpLA0KICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygxLjUsIDEsIDAsIDAuNSksICJjbSIpKSArDQogICAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIHNpemUgPSAibm9uZSIsIGNvbG9yID0gIm5vbmUiKSsNCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTEuNSwgMS41KSwNCiAgICAgICAgICAgICAgICAgICAgeGxpbSA9IGMoMCwgMTEuNSkpDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyBJbml0aWFsIHBvcHVsYXRpb24gc2l6ZSAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbWVhbnNfcG9wX3NpemUgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsblJSX21vZGVsX3BvcF9zaXplLA0KICBzcGVjcyA9IH4gcG9wX3NpemUgfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3QocG9wX3NpemUgPSBzZXEobWluKGRhdGEkcG9wX3NpemUsIG5hLnJtPVQpLCBtYXgoZGF0YSRwb3Bfc2l6ZSwgbmEucm09VCksIGJ5ID0gNTApLA0KICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID0gMCkpDQogICkgIyBDb25kaXRpb25hbCBlZmZlY3RzIG9uIGFzc2F5X3RlbXBfZGlmZiA9IDANCg0KIyBDYWxjdWxhdGUgcmFuZ2Ugb2YgdmFsdWVzIGZvciBlYWNoIGNhdGVnb3J5DQpyYW5nZV9kZiA8LSBkYXRhICU+JQ0KICBncm91cF9ieSh0cmFpdF90eXBlLCB3YXJtX2NvbGQpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWluX3BvcF9zaXplID0gbWluKHBvcF9zaXplLCBuYS5ybT1UKSwNCiAgICBtYXhfcG9wX3NpemUgPSBtYXgocG9wX3NpemUsIG5hLnJtPVQpDQogICkNCg0KZW1tZWFuc19wb3Bfc2l6ZSR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX3BvcF9zaXplJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfcG9wX3NpemUkd2FybV9jb2xkIDwtIGZhY3RvcihlbW1lYW5zX3BvcF9zaXplJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgVGFpbG9yIHByZWRpY3Rpb25zIHRvIHRoZSByYW5nZSBvZiB0aGUgZGF0YQ0KZW1tZWFuc19wb3Bfc2l6ZSA8LSBlbW1lYW5zX3BvcF9zaXplICU+JQ0KICBsZWZ0X2pvaW4ocmFuZ2VfZGYsIGJ5ID0gYygidHJhaXRfdHlwZSIsICJ3YXJtX2NvbGQiKSkgJT4lDQogIGZpbHRlcigNCiAgICBwb3Bfc2l6ZSA+PSBtaW5fcG9wX3NpemUsDQogICAgcG9wX3NpemUgPD0gbWF4X3BvcF9zaXplDQogICkNCg0KIyBDYWxjdWxhdGUgc2FtcGxlIHNpemVzIGFuZCBzdHVkeSBjb3VudHMgZm9yIHBvcHVsYXRpb24gc2l6ZQ0Kc2FtcGxlX3NpemVzX3BvcF9zaXplIDwtIGRhdGEgJT4lDQogIGZpbHRlcihpcy5uYShwb3Bfc2l6ZSk9PUZBTFNFKSAlPiUgDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBlc3RpbWF0ZXMgPSBuKCksDQogICAgc3R1ZGllcyA9IG5fZGlzdGluY3QocmVmKQ0KICApDQoNCiMgUGxvdA0KcG9wX3NpemUgPC0gDQpnZ3Bsb3QoKSArIA0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUpICsgDQogICAgZ2VvbV9wb2ludChkYXRhID0gZGF0YSwgICMgRWZmZWN0IHNpemVzLCBzY2FsZWQgYnkgcHJlY2lzaW9uDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHBvcF9zaXplLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5SUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5SUiksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX3BvcF9zaXplLCAjIFNoYWRlZCBhcmVhIGZvciBjcmVkaWJsZSBpbnRlcnZhbHMNCiAgICAgICAgICAgICAgICAgYWVzKHggPSBwb3Bfc2l6ZSwNCiAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICBmaWxsID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgYWxwaGEgPSAuNSkgKyANCiAgICAgZ2VvbV9saW5lKGRhdGEgPSBlbW1lYW5zX3BvcF9zaXplLCAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSBwb3Bfc2l6ZSwNCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKyAgDQogICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzX3BvcF9zaXplLCANCiAgICAgICAgICAgICAgYWVzKHggPSBJbmYsIA0KICAgICAgICAgICAgICAgICAgeSA9IGlmZWxzZSh3YXJtX2NvbGQgPT0gIldhcm0iLCAtMC45LCAtMS4zKSwgICMgU2FtcGxlIHNpemVzDQogICAgICAgICAgICAgICAgICBsYWJlbCA9IHBhc3RlMCgiayA9ICIsIGVzdGltYXRlcywgIiAoIiwgc3R1ZGllcywgIikiKSwNCiAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgIGhqdXN0ID0gMS4wNSwgc2l6ZSA9IDUsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgZmFjZXRfd3JhcCh+IHRyYWl0X3R5cGUsIG5jb2wgPSAxKSArICAjIERpZmZlcmVudCBwYW5lbHMgZm9yIGVhY2ggdHJhaXQNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICBsYWJzKHggPSAiUG9wdWxhdGlvbiBzaXplIiwgeSA9ICIiLCBjb2wgPSAiUmVnaW1lIikgKw0KICB0aGVtZV9idygpICsgDQogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoNCwgMTApKSsgDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDMwLCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTgpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgICAgYXhpcy50ZXh0LnkgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwLCANCiAgICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCBoanVzdCA9IDAuNSksDQogICAgICAgICAgYXhpcy50ZXh0LnggPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuNSksDQogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMjgpLA0KICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLCAxLCAwLCAwLjUpLCAiY20iKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiLCBjb2xvciA9ICJub25lIikrDQogICAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0xLjUsIDEuNSkpDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyBGdWxsIG1vZGVsICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucyBhdCB0aGUgbWVhbiBvZiBlYWNoIG1vZGVyYXRvcg0KZW1tZWFuc19mdWxsX21vZGVsIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5SUl9tb2RlbF9hbGxfbW9kZXJhdG9ycywNCiAgc3BlY3MgPSB+IGFzc2F5X3RlbXBfZGlmZiAqIHNlbGVjdF90ZW1wX2RpZmYgKiBnZW5fc2VsZWN0aW9uICogZ2VuX2NvbW1vbl9nYXJkZW4gfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICAgYXQgPSBsaXN0KGFzc2F5X3RlbXBfZGlmZiA9IHNlcShtaW4oZGF0YSRhc3NheV90ZW1wX2RpZmYpLCBtYXgoZGF0YSRhc3NheV90ZW1wX2RpZmYpLCBieSA9IDAuNSkpKSkgDQoNCg0KIyBDYWxjdWxhdGUgcmFuZ2Ugb2YgdmFsdWVzIGZvciBlYWNoIGNhdGVnb3J5DQpyYW5nZV9kZiA8LSBkYXRhICU+JQ0KICBncm91cF9ieSh0cmFpdF90eXBlLCB3YXJtX2NvbGQpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWluX2Fzc2F5X3RlbXBfZGlmZiA9IG1pbihhc3NheV90ZW1wX2RpZmYpLA0KICAgIG1heF9hc3NheV90ZW1wX2RpZmYgPSBtYXgoYXNzYXlfdGVtcF9kaWZmKQ0KICApDQoNCmVtbWVhbnNfZnVsbF9tb2RlbCR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX2Z1bGxfbW9kZWwkdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KZW1tZWFuc19mdWxsX21vZGVsJHdhcm1fY29sZCA8LSBmYWN0b3IoZW1tZWFuc19mdWxsX21vZGVsJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgVGFpbG9yIHByZWRpY3Rpb25zIHRvIHRoZSByYW5nZSBvZiB0aGUgZGF0YQ0KZW1tZWFuc19mdWxsX21vZGVsIDwtIGVtbWVhbnNfZnVsbF9tb2RlbCU+JQ0KICBsZWZ0X2pvaW4ocmFuZ2VfZGYsIGJ5ID0gYygidHJhaXRfdHlwZSIsICJ3YXJtX2NvbGQiKSkgJT4lDQogIGZpbHRlcigNCiAgICBhc3NheV90ZW1wX2RpZmYgPj0gbWluX2Fzc2F5X3RlbXBfZGlmZiwNCiAgICBhc3NheV90ZW1wX2RpZmYgPD0gbWF4X2Fzc2F5X3RlbXBfZGlmZg0KICApDQoNCiMgUGxvdA0KYXNzYXlfdGVtcCA8LQ0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArICANCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCAjIFZlcnRpY2FsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSkgKyANCiAgICBnZW9tX3BvaW50KGRhdGEgPSBkYXRhLCAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBhc3NheV90ZW1wX2RpZmYsIA0KICAgICAgICAgICAgICAgICAgICAgIHkgPSBsblJSLCANCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMS9zcXJ0KHZhcl9sblJSKSwgDQogICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICAgc2hhcGUgPSAyMSwgDQogICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuNywgDQogICAgICAgICAgICAgICAgICBzdHJva2UgPSAxLA0KICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjA1KSkgKyANCiAgICAgZ2VvbV9yaWJib24oZGF0YSA9IGVtbWVhbnNfZnVsbF9tb2RlbCwgIyBTaGFkZWQgYXJlYSBmb3IgY3JlZGlibGUgaW50ZXJ2YWxzDQogICAgICAgICAgICAgICAgIGFlcyh4ID0gYXNzYXlfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICBhbHBoYSA9IC41KSArIA0KICAgICBnZW9tX2xpbmUoZGF0YSA9IGVtbWVhbnNfZnVsbF9tb2RlbCwgICMgUHJlZGljdGVkIHJlZ3Jlc3Npb24gbGluZQ0KICAgICAgICAgICAgICAgYWVzKHkgPSBlbW1lYW4sDQogICAgICAgICAgICAgICAgICAgeCA9IGFzc2F5X3RlbXBfZGlmZiwNCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKyANCiAgICBnZW9tX3RleHQoZGF0YSA9IHNhbXBsZV9zaXplcywgDQogICAgICAgICAgICAgIGFlcyh4ID0gSW5mLCANCiAgICAgICAgICAgICAgICAgIHkgPSBpZmVsc2Uod2FybV9jb2xkID09ICJXYXJtIiwgLTIsIC0yLjc1KSwgICMgU2FtcGxlIHNpemVzDQogICAgICAgICAgICAgICAgICBsYWJlbCA9IHBhc3RlMCgiayA9ICIsIGVzdGltYXRlcywgIiAoIiwgc3R1ZGllcywgIikiKSwNCiAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgIGhqdXN0ID0gMS4wNSwgc2l6ZSA9IDUsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgDQogIGZhY2V0X3dyYXAofiB0cmFpdF90eXBlLCBuY29sID0gMSkgKyAjIERpZmZlcmVudCBwYW5lbHMgZm9yIGVhY2ggdHJhaXQNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiIzA2QjRCQSIsICIjRTgwNzU2IikpKw0KICBsYWJzKHggPSAiQXNzYXkgdGVtcGVyYXR1cmUgZGlmZmVyZW5jZSIsIHkgPSAibG5SUiIsDQogICAgICAgY29sID0gIlJlZ2ltZSIpICsNCiAgdGhlbWVfYncoKSArIA0KICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDQsIDEwKSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAzMCwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDI4KSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiLCBjb2wgPSAibm9uZSIpKw0KICAgIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygtMS41LCAxLjUpKQ0KDQoNCmFzc2F5X3RlbXAgLyAoc2VsX3RlbXBfZGlmZiB8IHBvcF9zaXplKSAvIChnZW5fc2VsZWN0aW9uIHwgZ2VuX2NvbW1vbl9nYXJkZW4pDQoNCmdnc2F2ZShmaWxlID0gImZpZy9maWd1cmVfNC5wbmciLCB3aWR0aCA9IDIwLCBoZWlnaHQgPSAzMiwgZHBpID0gNTAwKQ0KYGBgDQoNCg0KIyMgKipGaWd1cmUgNSoqIA0KDQpgYGB7ciwgZmlnLndpZHRoID0gMTIsIGZpZy5oZWlnaHQ9MTB9DQojIExvYWQgbW9kZWwNCmxuVlJfbW9kZWxfYXNzYXlfdGVtcF9kaWZmIDwtIHJlYWRSRFMoIlJEYXRhL2xuVlJfbW9kZWxfYXNzYXlfdGVtcF9kaWZmLnJkcyIpDQoNCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbWVhbnNfYXNzYXlfdGVtcF9kaWZmIDwtIGFzLmRhdGEuZnJhbWUoZW1tZWFucygNCiAgbG5WUl9tb2RlbF9hc3NheV90ZW1wX2RpZmYsDQogIHNwZWNzID0gfiBhc3NheV90ZW1wX2RpZmYgfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3QoYXNzYXlfdGVtcF9kaWZmID0gc2VxKG1pbihkYXRhJGFzc2F5X3RlbXBfZGlmZiksIG1heChkYXRhJGFzc2F5X3RlbXBfZGlmZiksIGJ5ID0gMC41KSkpDQogICkNCg0KIyBDYWxjdWxhdGUgcmFuZ2Ugb2YgdmFsdWVzIGZvciBlYWNoIGNhdGVnb3J5DQpyYW5nZV9kZiA8LSBkYXRhICU+JQ0KICBncm91cF9ieSh0cmFpdF90eXBlLCB3YXJtX2NvbGQpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWluX2Fzc2F5X3RlbXBfZGlmZiA9IG1pbihhc3NheV90ZW1wX2RpZmYpLA0KICAgIG1heF9hc3NheV90ZW1wX2RpZmYgPSBtYXgoYXNzYXlfdGVtcF9kaWZmKQ0KICApDQoNCmVtbWVhbnNfYXNzYXlfdGVtcF9kaWZmJHRyYWl0X3R5cGUgPC0gZmFjdG9yKGVtbWVhbnNfYXNzYXlfdGVtcF9kaWZmJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfYXNzYXlfdGVtcF9kaWZmJHdhcm1fY29sZCA8LSBmYWN0b3IoZW1tZWFuc19hc3NheV90ZW1wX2RpZmYkd2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiY29sZCIsICJ3YXJtIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJDb2xkIiwgIldhcm0iKSkNCg0KIyBUYWlsb3IgcHJlZGljdGlvbnMgdG8gdGhlIHJhbmdlIG9mIHRoZSBkYXRhDQplbW1lYW5zX2Fzc2F5X3RlbXBfZGlmZiA8LSBlbW1lYW5zX2Fzc2F5X3RlbXBfZGlmZiAlPiUNCiAgbGVmdF9qb2luKHJhbmdlX2RmLCBieSA9IGMoInRyYWl0X3R5cGUiLCAid2FybV9jb2xkIikpICU+JQ0KICBmaWx0ZXIoDQogICAgYXNzYXlfdGVtcF9kaWZmID49IG1pbl9hc3NheV90ZW1wX2RpZmYsDQogICAgYXNzYXlfdGVtcF9kaWZmIDw9IG1heF9hc3NheV90ZW1wX2RpZmYNCiAgKQ0KDQojIFBsb3QNCmdncGxvdCgpICsgDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgIyBIb3Jpem9udGFsIGxpbmUNCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwgDQogICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgIGFscGhhID0gMC43NSkgKyAgDQogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgIyBWZXJ0aWNhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUpICsgDQogICAgZ2VvbV9wb2ludChkYXRhID0gZGF0YSwgIyBFZmZlY3Qgc2l6ZXMsIHNjYWxlZCBieSBwcmVjaXNpb24NCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gYXNzYXlfdGVtcF9kaWZmLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5WUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5WUiksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX2Fzc2F5X3RlbXBfZGlmZiwgIyBTaGFkZWQgYXJlYSBmb3IgY3JlZGlibGUgaW50ZXJ2YWxzDQogICAgICAgICAgICAgICAgIGFlcyh4ID0gYXNzYXlfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGxvd2VyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICB5bWF4ID0gdXBwZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQsDQogICAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgICBhbHBoYSA9IC41KSArIA0KICAgICBnZW9tX2xpbmUoZGF0YSA9IGVtbWVhbnNfYXNzYXlfdGVtcF9kaWZmLCAgIyBQcmVkaWN0ZWQgcmVncmVzc2lvbiBsaW5lDQogICAgICAgICAgICAgICBhZXMoeSA9IGVtbWVhbiwNCiAgICAgICAgICAgICAgICAgICB4ID0gYXNzYXlfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArIA0KICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzLCANCiAgICAgICAgICAgICAgYWVzKHggPSBJbmYsIA0KICAgICAgICAgICAgICAgICAgeSA9IGlmZWxzZSh3YXJtX2NvbGQgPT0gIldhcm0iLCAtMiwgLTIuNzUpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICANCiAgZmFjZXRfd3JhcCh+IHRyYWl0X3R5cGUsIG5jb2wgPSAxKSArICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJBc3NheSB0ZW1wZXJhdHVyZSBkaWZmZXJlbmNlIiwgeSA9ICJsblZSIiwNCiAgICAgICBjb2wgPSAiUmVnaW1lIikgKw0KICB0aGVtZV9idygpICsgDQogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgOCkpKyANCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMjUsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxOCksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAyMikpICsNCiAgICBndWlkZXMoZmlsbCA9ICJub25lIiwgc2l6ZSA9ICJub25lIikrDQogICAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0zLjUsIDMuNSkpDQoNCmdnc2F2ZShmaWxlID0gImZpZy9maWd1cmVfNS5wbmciLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSAxMCwgZHBpID0gNTAwKQ0KYGBgDQoNCiMjICoqRmlndXJlIDYqKg0KDQpgYGB7ciwgZmlnLndpZHRoID0gMjAsIGZpZy5oZWlnaHQgPSAzMn0NCiMgTG9hZCBtb2RlbHMNCmxuVlJfbW9kZWxfc2VsX3RlbXBfZGlmZiA8LSByZWFkUkRTKCJSRGF0YS9sblZSX21vZGVsX3NlbF90ZW1wX2RpZmYucmRzIikNCmxuVlJfbW9kZWxfZ2VuX3NlbGVjdGlvbiA8LSByZWFkUkRTKCJSRGF0YS9sblZSX21vZGVsX2dlbl9zZWxlY3Rpb24ucmRzIikNCmxuVlJfbW9kZWxfZ2VuX2NvbW1vbl9nYXJkZW4gPC0gcmVhZFJEUygiUkRhdGEvbG5WUl9tb2RlbF9nZW5fY29tbW9uX2dhcmRlbi5yZHMiKQ0KbG5WUl9tb2RlbF9wb3Bfc2l6ZSA8LSByZWFkUkRTKCJSRGF0YS9sblZSX21vZGVsX3BvcF9zaXplLnJkcyIpDQpsblZSX21vZGVsX2FsbF9tb2RlcmF0b3JzIDwtIHJlYWRSRFMoIlJEYXRhL2xuVlJfbW9kZWxfYWxsX21vZGVyYXRvcnMucmRzIikNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIFNlbGVjdGlvbiB0ZW1wZXJhdHVyZSAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQojIEdlbmVyYXRlIHByZWRpY3Rpb25zDQplbW1lYW5zX3NlbF90ZW1wX2RpZmYgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsblZSX21vZGVsX3NlbF90ZW1wX2RpZmYsDQogIHNwZWNzID0gfiBzZWxlY3RfdGVtcF9kaWZmIHwgdHJhaXRfdHlwZSAqIHdhcm1fY29sZCwNCiAgYXQgPSBsaXN0KHNlbGVjdF90ZW1wX2RpZmYgPSBzZXEobWluKGRhdGEkc2VsZWN0X3RlbXBfZGlmZiksIG1heChkYXRhJHNlbGVjdF90ZW1wX2RpZmYpLCBieSA9IDAuMSksDQogICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPSAwKSkNCiAgKSAjIENvbmRpdGlvbmFsIGVmZmVjdHMgb24gYXNzYXlfdGVtcF9kaWZmID0gMA0KDQojIENhbGN1bGF0ZSByYW5nZSBvZiB2YWx1ZXMgZm9yIGVhY2ggY2F0ZWdvcnkNCnJhbmdlX2RmIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtaW5fc2VsZWN0X3RlbXBfZGlmZiA9IG1pbihzZWxlY3RfdGVtcF9kaWZmKSwNCiAgICBtYXhfc2VsZWN0X3RlbXBfZGlmZiA9IG1heChzZWxlY3RfdGVtcF9kaWZmKQ0KICApDQoNCmVtbWVhbnNfc2VsX3RlbXBfZGlmZiR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX3NlbF90ZW1wX2RpZmYkdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KZW1tZWFuc19zZWxfdGVtcF9kaWZmJHdhcm1fY29sZCA8LSBmYWN0b3IoZW1tZWFuc19zZWxfdGVtcF9kaWZmJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgVGFpbG9yIHByZWRpY3Rpb25zIHRvIHRoZSByYW5nZSBvZiB0aGUgZGF0YQ0KZW1tZWFuc19zZWxfdGVtcF9kaWZmIDwtIGVtbWVhbnNfc2VsX3RlbXBfZGlmZiAlPiUNCiAgbGVmdF9qb2luKHJhbmdlX2RmLCBieSA9IGMoInRyYWl0X3R5cGUiLCAid2FybV9jb2xkIikpICU+JQ0KICBmaWx0ZXIoDQogICAgc2VsZWN0X3RlbXBfZGlmZiA+PSBtaW5fc2VsZWN0X3RlbXBfZGlmZiwNCiAgICBzZWxlY3RfdGVtcF9kaWZmIDw9IG1heF9zZWxlY3RfdGVtcF9kaWZmDQogICkNCg0KIyBQbG90DQpzZWxfdGVtcF9kaWZmIDwtIA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsICAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBzZWxlY3RfdGVtcF9kaWZmLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5WUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5WUiksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX3NlbF90ZW1wX2RpZmYsICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IHNlbGVjdF90ZW1wX2RpZmYsDQogICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgIGFscGhhID0gLjUpICsgDQogICAgIGdlb21fbGluZShkYXRhID0gZW1tZWFuc19zZWxfdGVtcF9kaWZmLCAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSBzZWxlY3RfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArICANCiAgICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXMsIA0KICAgICAgICAgICAgICBhZXMoeCA9IEluZiwgDQogICAgICAgICAgICAgICAgICB5ID0gaWZlbHNlKHdhcm1fY29sZCA9PSAiV2FybSIsIC0yLCAtMi43NSksICAjIFNhbXBsZSBzaXplcw0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEuMDUsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGZhY2V0X3dyYXAofiB0cmFpdF90eXBlLCBuY29sID0gMSkgKyAgIyBEaWZmZXJlbnQgcGFuZWxzIGZvciBlYWNoIHRyYWl0DQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgbGFicyh4ID0gIlNlbGVjdGlvbiB0ZW1wZXJhdHVyZSBkaWZmZXJlbmNlIiwgeSA9ICJsblZSIiwgY29sID0gIlJlZ2ltZSIpICsNCiAgdGhlbWVfYncoKSArIA0KICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDIsIDgpKSsgDQogdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMzAsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxOCksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAyOCksDQogICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDEsIDAsIDAsIDApLCAiY20iKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiLCBjb2xvciA9ICJub25lIikrDQogICAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0zLjUsIDMuNSkpDQoNCiMjIyMjIyMjIyMjIyMjIEdlbmVyYXRpb25zIG9mIHNlbGVjdGlvbiAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbWVhbnNfZ2VuX3NlbGVjdGlvbiA8LSBhcy5kYXRhLmZyYW1lKGVtbWVhbnMoDQogIGxuVlJfbW9kZWxfZ2VuX3NlbGVjdGlvbiwNCiAgc3BlY3MgPSB+IGdlbl9zZWxlY3Rpb24gfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3QoZ2VuX3NlbGVjdGlvbiA9IHNlcShtaW4oZGF0YSRnZW5fc2VsZWN0aW9uKSwgbWF4KGRhdGEkZ2VuX3NlbGVjdGlvbiksIGJ5ID0gMSksDQogICAgICAgICAgICBhc3NheV90ZW1wX2RpZmYgPSAwKSkNCiAgKSAjIENvbmRpdGlvbmFsIGVmZmVjdHMgb24gYXNzYXlfdGVtcF9kaWZmID0gMA0KDQojIENhbGN1bGF0ZSByYW5nZSBvZiB2YWx1ZXMgZm9yIGVhY2ggY2F0ZWdvcnkNCnJhbmdlX2RmIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtaW5fZ2VuX3NlbGVjdGlvbiA9IG1pbihnZW5fc2VsZWN0aW9uKSwNCiAgICBtYXhfZ2VuX3NlbGVjdGlvbiA9IG1heChnZW5fc2VsZWN0aW9uKQ0KICApDQoNCmVtbWVhbnNfZ2VuX3NlbGVjdGlvbiR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX2dlbl9zZWxlY3Rpb24kdHJhaXRfdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImJvZHlfc2l6ZSIsICJmZWN1bmRpdHkiLCAic3Vydml2YWwiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkJvZHkgc2l6ZSIsICJGZWN1bmRpdHkiLCAiU3Vydml2YWwiKSkNCg0KZW1tZWFuc19nZW5fc2VsZWN0aW9uJHdhcm1fY29sZCA8LSBmYWN0b3IoZW1tZWFuc19nZW5fc2VsZWN0aW9uJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgVGFpbG9yIHByZWRpY3Rpb25zIHRvIHRoZSByYW5nZSBvZiB0aGUgZGF0YQ0KZW1tZWFuc19nZW5fc2VsZWN0aW9uIDwtIGVtbWVhbnNfZ2VuX3NlbGVjdGlvbiAlPiUNCiAgbGVmdF9qb2luKHJhbmdlX2RmLCBieSA9IGMoInRyYWl0X3R5cGUiLCAid2FybV9jb2xkIikpICU+JQ0KICBmaWx0ZXIoDQogICAgZ2VuX3NlbGVjdGlvbiA+PSBtaW5fZ2VuX3NlbGVjdGlvbiwNCiAgICBnZW5fc2VsZWN0aW9uIDw9IG1heF9nZW5fc2VsZWN0aW9uDQogICkNCg0KIyBQbG90DQpnZW5fc2VsZWN0aW9uIDwtIA0KZ2dwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCAjIEhvcml6b250YWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsICAjIEVmZmVjdCBzaXplcywgc2NhbGVkIGJ5IHByZWNpc2lvbg0KICAgICAgICAgICAgICAgICAgYWVzKHggPSBnZW5fc2VsZWN0aW9uLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5WUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5WUiksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX2dlbl9zZWxlY3Rpb24sICMgU2hhZGVkIGFyZWEgZm9yIGNyZWRpYmxlIGludGVydmFscw0KICAgICAgICAgICAgICAgICBhZXMoeCA9IGdlbl9zZWxlY3Rpb24sDQogICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgIGFscGhhID0gLjUpICsgDQogICAgIGdlb21fbGluZShkYXRhID0gZW1tZWFuc19nZW5fc2VsZWN0aW9uLCAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSBnZW5fc2VsZWN0aW9uLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArICANCiAgICAgZ2VvbV90ZXh0KGRhdGEgPSBzYW1wbGVfc2l6ZXMsIA0KICAgICAgICAgICAgICBhZXMoeCA9IEluZiwgDQogICAgICAgICAgICAgICAgICB5ID0gaWZlbHNlKHdhcm1fY29sZCA9PSAiV2FybSIsIC0yLCAtMi43NSksICAjIFNhbXBsZSBzaXplcw0KICAgICAgICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoImsgPSAiLCBlc3RpbWF0ZXMsICIgKCIsIHN0dWRpZXMsICIpIiksDQogICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICBoanVzdCA9IDEuMDUsIHNpemUgPSA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGZhY2V0X3dyYXAofiB0cmFpdF90eXBlLCBuY29sID0gMSkgKyAgIyBEaWZmZXJlbnQgcGFuZWxzIGZvciBlYWNoIHRyYWl0DQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMwNkI0QkEiLCAiI0U4MDc1NiIpKSsNCiAgbGFicyh4ID0gIk51bWJlciAgb2YgZ2VuZXJhdGlvbnMgb2Ygc2VsZWN0aW9uIiwgeSA9ICJsblJSIiwgY29sID0gIlJlZ2ltZSIpICsNCiAgdGhlbWVfYncoKSArIA0KICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDIsIDgpKSsgDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDMwLCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTgpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgICAgYXhpcy50ZXh0LnkgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwLCANCiAgICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCBoanVzdCA9IDAuNSksDQogICAgICAgICAgYXhpcy50ZXh0LnggPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuNSksDQogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMjgpLA0KICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygxLjUsIDAsIDAsIDApLCAiY20iKSkgKw0KICAgIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBzaXplID0gIm5vbmUiLCBjb2xvciA9ICJub25lIikrDQogICAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0zLjUsIDMuNSksDQogICAgICAgICAgICAgICAgICAgIHhsaW0gPSBjKDAsIDE1MCkpDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMgR2VuZXJhdGlvbnMgb2YgY29tbW9uIGdhcmRlbiAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KIyBHZW5lcmF0ZSBwcmVkaWN0aW9ucw0KZW1tZWFuc19nZW5fY29tbW9uX2dhcmRlbiA8LSBhcy5kYXRhLmZyYW1lKGVtbWVhbnMoDQogIGxuVlJfbW9kZWxfZ2VuX2NvbW1vbl9nYXJkZW4sDQogIHNwZWNzID0gfiBnZW5fY29tbW9uX2dhcmRlbiB8IHRyYWl0X3R5cGUgKiB3YXJtX2NvbGQsDQogIGF0ID0gbGlzdChnZW5fY29tbW9uX2dhcmRlbiA9IHNlcShtaW4oZGF0YSRnZW5fY29tbW9uX2dhcmRlbiksIG1heChkYXRhJGdlbl9jb21tb25fZ2FyZGVuKSwgYnkgPSAxKSwNCiAgICAgICAgICAgIGFzc2F5X3RlbXBfZGlmZiA9IDApKQ0KICApICMgQ29uZGl0aW9uYWwgZWZmZWN0cyBvbiBhc3NheV90ZW1wX2RpZmYgPSAwDQoNCiMgQ2FsY3VsYXRlIHJhbmdlIG9mIHZhbHVlcyBmb3IgZWFjaCBjYXRlZ29yeQ0KcmFuZ2VfZGYgPC0gZGF0YSAlPiUNCiAgZ3JvdXBfYnkodHJhaXRfdHlwZSwgd2FybV9jb2xkKSAlPiUNCiAgc3VtbWFyaXplKA0KICAgIG1pbl9nZW5fY29tbW9uX2dhcmRlbiA9IG1pbihnZW5fY29tbW9uX2dhcmRlbiksDQogICAgbWF4X2dlbl9jb21tb25fZ2FyZGVuID0gbWF4KGdlbl9jb21tb25fZ2FyZGVuKQ0KICApDQoNCmVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4kdHJhaXRfdHlwZSA8LSBmYWN0b3IoZW1tZWFuc19nZW5fY29tbW9uX2dhcmRlbiR0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYm9keV9zaXplIiwgImZlY3VuZGl0eSIsICJzdXJ2aXZhbCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQm9keSBzaXplIiwgIkZlY3VuZGl0eSIsICJTdXJ2aXZhbCIpKQ0KDQplbW1lYW5zX2dlbl9jb21tb25fZ2FyZGVuJHdhcm1fY29sZCA8LSBmYWN0b3IoZW1tZWFuc19nZW5fY29tbW9uX2dhcmRlbiR3YXJtX2NvbGQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJjb2xkIiwgIndhcm0iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkNvbGQiLCAiV2FybSIpKQ0KDQojIFRhaWxvciBwcmVkaWN0aW9ucyB0byB0aGUgcmFuZ2Ugb2YgdGhlIGRhdGENCmVtbWVhbnNfZ2VuX2NvbW1vbl9nYXJkZW4gPC0gZW1tZWFuc19nZW5fY29tbW9uX2dhcmRlbiAlPiUNCiAgbGVmdF9qb2luKHJhbmdlX2RmLCBieSA9IGMoInRyYWl0X3R5cGUiLCAid2FybV9jb2xkIikpICU+JQ0KICBmaWx0ZXIoDQogICAgZ2VuX2NvbW1vbl9nYXJkZW4gPj0gbWluX2dlbl9jb21tb25fZ2FyZGVuLA0KICAgIGdlbl9jb21tb25fZ2FyZGVuIDw9IG1heF9nZW5fY29tbW9uX2dhcmRlbg0KICApDQoNCiMgUGxvdA0KZ2VuX2NvbW1vbl9nYXJkZW4gPC0gDQpnZ3Bsb3QoKSArIA0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUpICsgDQogICAgZ2VvbV9wb2ludChkYXRhID0gZGF0YSwgICMgRWZmZWN0IHNpemVzLCBzY2FsZWQgYnkgcHJlY2lzaW9uDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IGdlbl9jb21tb25fZ2FyZGVuLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5WUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5WUiksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX2dlbl9jb21tb25fZ2FyZGVuLCAjIFNoYWRlZCBhcmVhIGZvciBjcmVkaWJsZSBpbnRlcnZhbHMNCiAgICAgICAgICAgICAgICAgYWVzKHggPSBnZW5fY29tbW9uX2dhcmRlbiwNCiAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICBmaWxsID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgYWxwaGEgPSAuNSkgKyANCiAgICAgZ2VvbV9saW5lKGRhdGEgPSBlbW1lYW5zX2dlbl9jb21tb25fZ2FyZGVuLCAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSBnZW5fY29tbW9uX2dhcmRlbiwNCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKyAgDQogICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzLCANCiAgICAgICAgICAgICAgYWVzKHggPSBJbmYsIA0KICAgICAgICAgICAgICAgICAgeSA9IGlmZWxzZSh3YXJtX2NvbGQgPT0gIldhcm0iLCAtMiwgLTIuNzUpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBmYWNldF93cmFwKH4gdHJhaXRfdHlwZSwgbmNvbCA9IDEpICsgICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJOdW1iZXIgb2YgZ2VuZXJhdGlvbnMgb2YgY29tbW9uIGdhcmRlbiIsIHkgPSAiIiwgY29sID0gIlJlZ2ltZSIpICsNCiAgdGhlbWVfYncoKSArIA0KICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDIsIDgpKSsgDQogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDMwLCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTgpLA0KICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgICAgYXhpcy50ZXh0LnkgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwLCANCiAgICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCBoanVzdCA9IDAuNSksDQogICAgICAgICAgYXhpcy50ZXh0LnggPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwNCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuNSksDQogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMjgpLA0KICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygxLjUsIDEsIDAsIDAuNSksICJjbSIpKSArDQogICAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIHNpemUgPSAibm9uZSIsIGNvbG9yID0gIm5vbmUiKSsNCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTMuNSwgMy41KSwNCiAgICAgICAgICAgICAgICAgICAgeGxpbSA9IGMoMCwgMTEuNSkpDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyBJbml0aWFsIHBvcHVsYXRpb24gc2l6ZSAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCiMgR2VuZXJhdGUgcHJlZGljdGlvbnMNCmVtbWVhbnNfcG9wX3NpemUgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsblZSX21vZGVsX3BvcF9zaXplLA0KICBzcGVjcyA9IH4gcG9wX3NpemUgfCB0cmFpdF90eXBlICogd2FybV9jb2xkLA0KICBhdCA9IGxpc3QocG9wX3NpemUgPSBzZXEobWluKGRhdGEkcG9wX3NpemUsIG5hLnJtPVQpLCBtYXgoZGF0YSRwb3Bfc2l6ZSwgbmEucm09VCksIGJ5ID0gNTApLA0KICAgICAgICAgICAgYXNzYXlfdGVtcF9kaWZmID0gMCkpDQogICkgIyBDb25kaXRpb25hbCBlZmZlY3RzIG9uIGFzc2F5X3RlbXBfZGlmZiA9IDANCg0KIyBDYWxjdWxhdGUgcmFuZ2Ugb2YgdmFsdWVzIGZvciBlYWNoIGNhdGVnb3J5DQpyYW5nZV9kZiA8LSBkYXRhICU+JQ0KICBncm91cF9ieSh0cmFpdF90eXBlLCB3YXJtX2NvbGQpICU+JQ0KICBzdW1tYXJpemUoDQogICAgbWluX3BvcF9zaXplID0gbWluKHBvcF9zaXplLCBuYS5ybT1UKSwNCiAgICBtYXhfcG9wX3NpemUgPSBtYXgocG9wX3NpemUsIG5hLnJtPVQpDQogICkNCg0KZW1tZWFuc19wb3Bfc2l6ZSR0cmFpdF90eXBlIDwtIGZhY3RvcihlbW1lYW5zX3BvcF9zaXplJHRyYWl0X3R5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJib2R5X3NpemUiLCAiZmVjdW5kaXR5IiwgInN1cnZpdmFsIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJCb2R5IHNpemUiLCAiRmVjdW5kaXR5IiwgIlN1cnZpdmFsIikpDQoNCmVtbWVhbnNfcG9wX3NpemUkd2FybV9jb2xkIDwtIGZhY3RvcihlbW1lYW5zX3BvcF9zaXplJHdhcm1fY29sZCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoImNvbGQiLCAid2FybSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQ29sZCIsICJXYXJtIikpDQoNCiMgVGFpbG9yIHByZWRpY3Rpb25zIHRvIHRoZSByYW5nZSBvZiB0aGUgZGF0YQ0KZW1tZWFuc19wb3Bfc2l6ZSA8LSBlbW1lYW5zX3BvcF9zaXplICU+JQ0KICBsZWZ0X2pvaW4ocmFuZ2VfZGYsIGJ5ID0gYygidHJhaXRfdHlwZSIsICJ3YXJtX2NvbGQiKSkgJT4lDQogIGZpbHRlcigNCiAgICBwb3Bfc2l6ZSA+PSBtaW5fcG9wX3NpemUsDQogICAgcG9wX3NpemUgPD0gbWF4X3BvcF9zaXplDQogICkNCg0KIyBDYWxjdWxhdGUgc2FtcGxlIHNpemVzIGFuZCBzdHVkeSBjb3VudHMgZm9yIHBvcHVsYXRpb24gc2l6ZQ0Kc2FtcGxlX3NpemVzX3BvcF9zaXplIDwtIGRhdGEgJT4lDQogIGZpbHRlcihpcy5uYShwb3Bfc2l6ZSk9PUZBTFNFKSAlPiUgDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBlc3RpbWF0ZXMgPSBuKCksDQogICAgc3R1ZGllcyA9IG5fZGlzdGluY3QocmVmKQ0KICApDQoNCiMgUGxvdA0KcG9wX3NpemUgPC0gDQpnZ3Bsb3QoKSArIA0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUpICsgDQogICAgZ2VvbV9wb2ludChkYXRhID0gZGF0YSwgICMgRWZmZWN0IHNpemVzLCBzY2FsZWQgYnkgcHJlY2lzaW9uDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IHBvcF9zaXplLCANCiAgICAgICAgICAgICAgICAgICAgICB5ID0gbG5WUiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEvc3FydCh2YXJfbG5WUiksIA0KICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgIHNoYXBlID0gMjEsIA0KICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcsIA0KICAgICAgICAgICAgICAgICAgc3Ryb2tlID0gMSwNCiAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4wNSkpICsgDQogICAgIGdlb21fcmliYm9uKGRhdGEgPSBlbW1lYW5zX3BvcF9zaXplLCAjIFNoYWRlZCBhcmVhIGZvciBjcmVkaWJsZSBpbnRlcnZhbHMNCiAgICAgICAgICAgICAgICAgYWVzKHggPSBwb3Bfc2l6ZSwNCiAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsb3dlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgeW1heCA9IHVwcGVyLkhQRCwgDQogICAgICAgICAgICAgICAgICAgICBmaWxsID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgICAgYWxwaGEgPSAuNSkgKyANCiAgICAgZ2VvbV9saW5lKGRhdGEgPSBlbW1lYW5zX3BvcF9zaXplLCAjIFByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUNCiAgICAgICAgICAgICAgIGFlcyh5ID0gZW1tZWFuLA0KICAgICAgICAgICAgICAgICAgIHggPSBwb3Bfc2l6ZSwNCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICBncm91cCA9IHdhcm1fY29sZCksIA0KICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKyAgDQogICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzX3BvcF9zaXplLCANCiAgICAgICAgICAgICAgYWVzKHggPSBJbmYsIA0KICAgICAgICAgICAgICAgICAgeSA9IGlmZWxzZSh3YXJtX2NvbGQgPT0gIldhcm0iLCAtMiwgLTIuNzUpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBmYWNldF93cmFwKH4gdHJhaXRfdHlwZSwgbmNvbCA9IDEpICsgICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJQb3B1bGF0aW9uIHNpemUiLCB5ID0gIiIsIGNvbCA9ICJSZWdpbWUiKSArDQogIHRoZW1lX2J3KCkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLCA4KSkrIA0KICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAzMCwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwNCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICAgIGF4aXMudGV4dC55ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCwgDQogICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICAgIGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAyMCksDQogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpLA0KICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDI4KSwNCiAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoMCwgMSwgMCwgMC41KSwgImNtIikpICsNCiAgICBndWlkZXMoZmlsbCA9ICJub25lIiwgc2l6ZSA9ICJub25lIiwgY29sb3IgPSAibm9uZSIpKw0KICAgIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygtMy41LCAzLjUpKQ0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMgRnVsbCBtb2RlbCAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQojIEdlbmVyYXRlIHByZWRpY3Rpb25zIGF0IHRoZSBtZWFuIG9mIGVhY2ggbW9kZXJhdG9yDQplbW1lYW5zX2Z1bGxfbW9kZWwgPC0gYXMuZGF0YS5mcmFtZShlbW1lYW5zKA0KICBsblZSX21vZGVsX2FsbF9tb2RlcmF0b3JzLA0KICBzcGVjcyA9IH4gYXNzYXlfdGVtcF9kaWZmICogc2VsZWN0X3RlbXBfZGlmZiAqIGdlbl9zZWxlY3Rpb24gKiBnZW5fY29tbW9uX2dhcmRlbiB8IHRyYWl0X3R5cGUgKiB3YXJtX2NvbGQsDQogICBhdCA9IGxpc3QoYXNzYXlfdGVtcF9kaWZmID0gc2VxKG1pbihkYXRhJGFzc2F5X3RlbXBfZGlmZiksIG1heChkYXRhJGFzc2F5X3RlbXBfZGlmZiksIGJ5ID0gMC41KSkpKSANCg0KDQojIENhbGN1bGF0ZSByYW5nZSBvZiB2YWx1ZXMgZm9yIGVhY2ggY2F0ZWdvcnkNCnJhbmdlX2RmIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KHRyYWl0X3R5cGUsIHdhcm1fY29sZCkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtaW5fYXNzYXlfdGVtcF9kaWZmID0gbWluKGFzc2F5X3RlbXBfZGlmZiksDQogICAgbWF4X2Fzc2F5X3RlbXBfZGlmZiA9IG1heChhc3NheV90ZW1wX2RpZmYpDQogICkNCg0KZW1tZWFuc19mdWxsX21vZGVsJHRyYWl0X3R5cGUgPC0gZmFjdG9yKGVtbWVhbnNfZnVsbF9tb2RlbCR0cmFpdF90eXBlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiYm9keV9zaXplIiwgImZlY3VuZGl0eSIsICJzdXJ2aXZhbCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQm9keSBzaXplIiwgIkZlY3VuZGl0eSIsICJTdXJ2aXZhbCIpKQ0KDQplbW1lYW5zX2Z1bGxfbW9kZWwkd2FybV9jb2xkIDwtIGZhY3RvcihlbW1lYW5zX2Z1bGxfbW9kZWwkd2FybV9jb2xkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiY29sZCIsICJ3YXJtIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJDb2xkIiwgIldhcm0iKSkNCg0KIyBUYWlsb3IgcHJlZGljdGlvbnMgdG8gdGhlIHJhbmdlIG9mIHRoZSBkYXRhDQplbW1lYW5zX2Z1bGxfbW9kZWwgPC0gZW1tZWFuc19mdWxsX21vZGVsJT4lDQogIGxlZnRfam9pbihyYW5nZV9kZiwgYnkgPSBjKCJ0cmFpdF90eXBlIiwgIndhcm1fY29sZCIpKSAlPiUNCiAgZmlsdGVyKA0KICAgIGFzc2F5X3RlbXBfZGlmZiA+PSBtaW5fYXNzYXlfdGVtcF9kaWZmLA0KICAgIGFzc2F5X3RlbXBfZGlmZiA8PSBtYXhfYXNzYXlfdGVtcF9kaWZmDQogICkNCg0KIyBQbG90DQpnZ3Bsb3QoKSArIA0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsICMgSG9yaXpvbnRhbCBsaW5lDQogICAgICAgICAgICAgICBsaW5ldHlwZSA9IDIsIA0KICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICBhbHBoYSA9IDAuNzUpICsgIA0KICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsICMgVmVydGljYWwgbGluZQ0KICAgICAgICAgICAgICAgbGluZXR5cGUgPSAyLCANCiAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgYWxwaGEgPSAwLjc1KSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsICMgRWZmZWN0IHNpemVzLCBzY2FsZWQgYnkgcHJlY2lzaW9uDQogICAgICAgICAgICAgICAgICBhZXMoeCA9IGFzc2F5X3RlbXBfZGlmZiwgDQogICAgICAgICAgICAgICAgICAgICAgeSA9IGxuVlIsIA0KICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxL3NxcnQodmFyX2xuVlIpLCANCiAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgICBzaGFwZSA9IDIxLCANCiAgICAgICAgICAgICAgICAgIGFscGhhID0gMC43LCANCiAgICAgICAgICAgICAgICAgIHN0cm9rZSA9IDEsDQogICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IDAuMDUpKSArIA0KICAgICBnZW9tX3JpYmJvbihkYXRhID0gZW1tZWFuc19mdWxsX21vZGVsLCAjIFNoYWRlZCBhcmVhIGZvciBjcmVkaWJsZSBpbnRlcnZhbHMNCiAgICAgICAgICAgICAgICAgYWVzKHggPSBhc3NheV90ZW1wX2RpZmYsDQogICAgICAgICAgICAgICAgICAgICB5bWluID0gbG93ZXIuSFBELCANCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSB1cHBlci5IUEQsIA0KICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHdhcm1fY29sZCwNCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICAgIGFscGhhID0gLjUpICsgDQogICAgIGdlb21fbGluZShkYXRhID0gZW1tZWFuc19mdWxsX21vZGVsLCAgIyBQcmVkaWN0ZWQgcmVncmVzc2lvbiBsaW5lDQogICAgICAgICAgICAgICBhZXMoeSA9IGVtbWVhbiwNCiAgICAgICAgICAgICAgICAgICB4ID0gYXNzYXlfdGVtcF9kaWZmLA0KICAgICAgICAgICAgICAgICAgIGNvbG9yID0gd2FybV9jb2xkLA0KICAgICAgICAgICAgICAgICAgIGdyb3VwID0gd2FybV9jb2xkKSwgDQogICAgICAgICAgICAgICBzaXplID0gMS41KSArIA0KICAgIGdlb21fdGV4dChkYXRhID0gc2FtcGxlX3NpemVzLCANCiAgICAgICAgICAgICAgYWVzKHggPSBJbmYsIA0KICAgICAgICAgICAgICAgICAgeSA9IGlmZWxzZSh3YXJtX2NvbGQgPT0gIldhcm0iLCAtMiwgLTIuNzUpLCAgIyBTYW1wbGUgc2l6ZXMNCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGFzdGUwKCJrID0gIiwgZXN0aW1hdGVzLCAiICgiLCBzdHVkaWVzLCAiKSIpLA0KICAgICAgICAgICAgICAgICAgY29sb3IgPSB3YXJtX2NvbGQpLCANCiAgICAgICAgICAgICAgaGp1c3QgPSAxLjA1LCBzaXplID0gNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICANCiAgZmFjZXRfd3JhcCh+IHRyYWl0X3R5cGUsIG5jb2wgPSAxKSArICMgRGlmZmVyZW50IHBhbmVscyBmb3IgZWFjaCB0cmFpdA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMDZCNEJBIiwgIiNFODA3NTYiKSkrDQogIGxhYnMoeCA9ICJBc3NheSB0ZW1wZXJhdHVyZSBkaWZmZXJlbmNlIiwgeSA9ICJsblZSIiwNCiAgICAgICBjb2wgPSAiUmVnaW1lIikgKw0KICB0aGVtZV9idygpICsgDQogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMiwgOCkpKyANCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMzAsIGNvbG9yID0gImJsYWNrIiksDQogICAgICAgICAgbGVnZW5kLnRpdGxlID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemUgPSAxOCksDQogICAgICAgICAgbGVnZW5kLnRleHQgPSBnZ3Bsb3QyOjplbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgICBheGlzLnRleHQueSA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjAsIA0KICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgICBheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplID0gMjApLA0KICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMS41KSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAyOCkpICsNCiAgICBndWlkZXMoZmlsbCA9ICJub25lIiwgc2l6ZSA9ICJub25lIikrDQogICAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0zLjUsIDMuNSkpDQoNCmFzc2F5X3RlbXAgLyAoc2VsX3RlbXBfZGlmZiB8IHBvcF9zaXplKSAvIChnZW5fc2VsZWN0aW9uIHwgZ2VuX2NvbW1vbl9nYXJkZW4pDQoNCmdnc2F2ZShmaWxlID0gImZpZy9maWd1cmVfNi5wbmciLCB3aWR0aCA9IDIwLCBoZWlnaHQgPSAzMiwgZHBpID0gNTAwKQ0KYGBgDQoNCiMjICoqRmlndXJlIFMxKioNCg0KIyAqKlBhY2thZ2UgaW5mb3JtYXRpb24qKiANCg0KYGBge3J9DQpzZXNzaW9uSW5mbygpDQpgYGANCg0K